当前位置: 首页 > 知识库问答 >
问题:

运行时。exec字符串给出语法错误

鄢朝斑
2023-03-14

我正在使用runtime.exec尝试将一个. SQL脚本执行到我本地的SQLite数据库文件中。我目前正在MacOS上运行这个。

    Runtime runtime = Runtime.getRuntime();
    try
    {
        Process process = runtime.exec("sqlite3 /Users/Documents/Uni/Music\\ Player/src/Common/database.db  < /Users/Documents/Uni/Music\\ Player/src/Common/database.sql");

        BufferedReader stdError = new BufferedReader(newInputStreamReader(process.getErrorStream()));

        try {
            if (process.waitFor() != 0) {
                String s = "";
                System.err.println("exit value = " + process.exitValue());
                System.out.println("Here is the standard error of the command (if any):");
                while ((s = stdError.readLine()) != null) {
                    System.out.println(s);
                }
            }
        } catch (InterruptedException e) {
            System.err.println(e);
        } 

这是我当前使用的代码。如果我通过终端执行命令,它将成功执行,我的数据库将用.SQL脚本的内容更新。

然而,当我通过代码执行此操作时,我会得到错误:

错误:“Player”附近:语法错误以及进程退出

我一辈子都找不到字符串语法有什么问题。我尝试了多种不同的方法来转义字符串中的空格,但没有成功。有什么想法吗?

共有2个答案

丘畅
2023-03-14
匿名用户

如果您查看“Runtime.exec()的文档,并遵循实用程序方法的扩展,您将会看到:

更准确地说,使用由调用new StringTokenizer(命令)创建的StringTokenizer将命令字符串分解为标记,而不需要进一步修改字符类别

现在,如果您尝试使用< code>StringTokenizer单独断开字符串,您会看到它被分成:

sqlite3
/Users/Documents/Uni/Music\
Player/src/Common/database.db
<
/Users/Documents/Uni/Music\
Player/src/Common/database.sql

与其将整个命令传递给exec,不如使用接受命令及其参数为字符串[]的exec版本:

runtime.exec(new String[]{
    "sqlite3",
    " /Users/Documents/Uni/Music Player/src/Common/database.db"
    });

然而,像这样阅读输入是行不通的。当您键入命令时,shell会对其进行解释。除了< code>exec之外,您可能希望使用< code>Process,如使用来自Java的重定向标准输入和标准输出运行外部程序中所示。

劳和歌
2023-03-14

让我们创建一个< code>Path并让它为您生成文件路径,而不是尝试使用手动硬编码的< code>String来生成文件路径。这很容易使用,而且无论操作系统或文件系统是什么,都可以生成正确的文件路径。

将当前的exec命令替换为this以实现该更改:

Path parentDirectory = Paths.get("Users","Documents","Uni","Music Player","src","Common");
String sqlCommand = "sqlite3 database.db < database.sql";        
Process process = runtime.exec(sqlCommand, null, parentDirectory.toFile());

这将运行“sqlite3数据库.db

但是,尽管修复了原始问题,但您的代码还包含与使用文件重定向相关的另一个问题。文件重定向方式

下面是修复了这两个问题的代码:

Path parentDirectory = Paths.get("Users","Documents","Uni","Music Player","src","Common");
String sqlCommand = "sqlite3 database.db"; 
File inputSqlFile = new File("database.sql");        

Process process = new ProcessBuilder()
        .directory(parentDirectory.toFile())
        .command(sqlCommand)
        .redirectInput(Redirect.from(inputSqlFile))
        .start();

此代码使用 ProcessBuilder 将目录设置为与以前相同的父目录,但该命令已修改为删除文件重定向,而是使用 redirectinput() 方法实现文件重定向。这与“sqlite3 数据库”完成相同的操作.db

编辑:

上面的代码不起作用,所以我试图修复它,并添加了调试语句来帮助跟踪问题:

Path databasePath = FileSystems.getDefault().getPath("Users", "Documents", "Uni", "Music Player", "src", "Common", "database.db");
Path sqlPath = FileSystems.getDefault().getPath("Users", "Documents", "Uni", "Music Player", "src", "Common", "database.sql");

File database = databasePath.toFile().getAbsoluteFile();
File sqlFile = sqlPath.toFile().getAbsoluteFile();

System.out.println("Database location:\n\t" + database.getCanonicalPath());
System.out.println("SQL file location:\n\t" + sqlFile.getCanonicalPath());

assert database.exists() && database.isFile() && database.canRead() && database.canWrite(): "No such database file!";
assert sqlFile.exists() && sqlFile.isFile() && database.canRead() : "No such SQL file!";

String[] sqlCommand = {"sqlite3", database.getCanonicalPath()};
Redirect sqlInput = Redirect.from(sqlFile);
File workingDirectory = database.getParentFile().getCanonicalFile();

System.out.println("Running this command:\n\t" +
sqlCommand[0] + sqlCommand[1] + "<" + sqlInput.file().getCanonicalPath());

Process process = new ProcessBuilder()
        .directory(workingDirectory)
        .command(sqlCommand)
        .redirectInput(sqlInput)
        .start();

这是相同的代码,删除了调试代码并进行了轻微清理:

File database = FileSystems.getDefault()
    .getPath("Users", "Documents", "Uni","Music Player", "src", "Common", "database.db")
    .toFile().getAbsoluteFile();
File sqlFile = FileSystems.getDefault()
    .getPath("Users", "Documents", "Uni","Music Player", "src", "Common", "database.sql")
    .toFile().getAbsoluteFile();

String[] sqlCommand = {"sqlite3", database.getCanonicalPath()};
Redirect sqlInput = Redirect.from(sqlFile);
File workingDirectory = database.getParentFile().getCanonicalFile();

Process process = new ProcessBuilder()
        .directory(workingDirectory)
        .command(sqlCommand)
        .redirectInput(sqlInput)
        .start();

 类似资料:
  • 有人能告诉我这个: 在第二行,我得到一个错误。但这行得通: 我需要更多的文字后,我打印的名称。有人知道怎么做吗?

  • 通常我不会在这里发布语法错误,但这个案例对我来说有点可疑。我试图用一个字符串组合一个常数。我在本地主机上工作正常,但当我在web服务器上推送项目时,它会告诉我: 代码: 和 这与不同的PHP版本有关吗?(5.5在网络服务器,7.0localhost) 最新消息 代码中的一些更新:

  • 我有一个XML字符串,如下所示: 现在,我用名称数据将其解组到类中。java,它将变量作为CustomerInfo的另一个类。JAVA 但在解组时,我得到了一个错误作为意外元素(uri:)https://www.google/com,本地:“数据”)。预期的元素为

  • 我正在尝试运行基本的hello-world应用程序。我完全沮丧,找不到解决这个问题的办法。怎么了?我已经尝试了这些解决方案,但仍然没有运气。请帮助我:'(

  • 谁能告诉我这个密码是什么?我尝试了所有方法,但不知道为什么它总是给我这个错误: 第3行出现解析错误:...","简称":"简单","长" - 应为“STRING”、“NUMBER”、“NULL”、“TRUE”、“FALSE”、“{”和“[” 谢谢

  • 问题内容: 我正在制作基于文本的骰子滚轴。它接受“ 2d10 + 5”之类的字符串,并作为滚动结果返回一个字符串。我的问题出现在令牌生成器中,该令牌生成器将字符串拆分为有用的部分,以便我解析为信息。 这会产生奇怪的意外结果。我不知道是什么原因造成的。可能是正则表达式,我的误解,或者Java只是Java。这是正在发生的事情: 产生字符串数组。这是对的。 产生字符串数组。这是对的。 产生字符串数组。这