【问题标题】:Java String.Split while printwriting [duplicate]打印时的Java String.Split [重复]
【发布时间】:2018-07-23 18:13:59
【问题描述】:

我目前正在开发一个搜索输出系统,该系统在目录中搜索文件中的特定短语,匹配它,然后将其输出到日志文件。我有一个看起来像这样的代码 sn-p 问题:

int j = 0;
for(String currentMatch : lineMatch) {

                    String[] split = fileList.get(j).toString().split("\\\\");
                    match.write(split[3] + " : " + currentMatch + "\r\n");
                    match.flush();
                    j++;
}

fileList 是具有匹配结果的文件名的数组列表,filePath 是文件路径的数组列表。我使用 split[3] 返回了该目录中我感兴趣的第四个文件夹的名称。

然后输出文件变得有点时髦。这个有问题的目录有大约 40 个唯一名称,但日志最终看起来像这样:

    dir1 :   matchingline
    dir2 :   matchingline
    dir3 :   matchingline
    dir3 :   matchingline
    ...     (x543)
    dir4 :   matchingline

等等。目录 3 应该只有 88 行匹配,并且最终有 455 行属于其他目录。知道为什么会这样吗?是因为我在 PrintWriter 中间使用了一个作业,还是我在这里遗漏了一些简单的东西?

编辑:为清楚起见列出了变量。

match = 用于打印到输出的 Printwriter 对象。

lineMatch = ArrayList() - 包含当前匹配文件的目录路径

fileMatch = ArrayList() - 包含匹配的文件名。

使用

split[3] 是因为匹配的文件始终在第 4 个目录中找到,例如。 C:\用户\程序\程序名\

/r/n 用于在 windows 上保持格式。

这是一个个人项目,所以我不太关心使其可移植性。

编辑添加了用于初始化arraylist的方法。

public static void addFiles(String dirPath) {

        File dir = new File(dirPath);
        File[] files = dir.listFiles();


        try {
            if(files.length == 0) {

                emptyFilePath.add(dirPath);

            }
            else {
                for (File currentFile : files) {
                    if(currentFile.isFile()) {

                        fileList.add(currentFile);
                        filePath.add(currentFile.getPath());
                    }
                    else if (currentFile.isDirectory()) {

                        addFiles(currentFile.getAbsolutePath());

                    }

                }
            }

        }catch(Exception e) {
            e.printStackTrace();
        }
    }

以及生成lineMatch的代码:

while(i < fileList.size()) {

                File files = new File(filePath.get(i));
                Scanner file = new Scanner(files);
                try {

                    while(file.hasNextLine()) {
                        String currentLine = file.nextLine();
                        if(currentLine.contains(searchString)) {
                            lineMatch.add(currentLine);
                        }

                    }

                }finally {
                    file.close();
                }

                i++;

            }

【问题讨论】:

  • 编辑仍然不够清楚。 lineMatch 是如何生成的? fileMatch 是如何生成的?很明显,它们将是列表。但是这些列表是如何初始化的呢?
  • 贴在上面,基本上只是递归搜索指定目录和所有子目录的方法
  • 这里的答案不同 - 这是因为虽然 lineMatch 已更新并将字符串数量减少到仅匹配的字符串,但 filePath 没有,并且具有已跳过的 ArrayList 元素的引用位置。

标签: java split printwriter


【解决方案1】:

您的代码有很多可疑之处。

  • LineMatchFileList 是变量吗?如果是这样,那么您应该将它们写成变量,即lineMatchfileList (lowerCamelCase)。否则会使读者和语法高亮者感到困惑。
  • 你使用split[3],这看起来很可疑。
  • 如果您使用split("\\\\") 来获取目录路径部分,请注意您的代码不可移植,它只能在Windows 上运行。如果您想将路径拆分为多个部分,最好使用 API。
  • 为了理解问题,看看LineMatchFileList 是如何生成的会很有用,否则就无法理解代码中出了什么问题。
  • 如果matchPrintWriterPrintStream,则应使用println()format("...%n") 而不是write(... + "\r\n")。同样,因为您的代码不可移植。在 Unix 上,行尾只有 \n,而不是 \r\n

实际问题在于您的程序逻辑。您的变量lineMatch 包含找到的所有 个文件的命中。因为您不会为每个文件生成单独的lineMatch,而是为所有文件生成一个单独的lineMatch。至少从您目前发布的代码来看是这样的。

看起来您要编程的是grep 的简单版本(或者,在 DOS 上,find)。您的部分逻辑是正确的,例如,您如何使用递归下降到目录树。不要收集所有匹配项然后打印,而是在遍历目录树时查找并打印匹配项。

一般来说,如果你避免使用全局变量,你最终会得到更少的错误。您首先遇到了问题,因为您的变量 LineMatchFileList 是全局变量。避免全局变量,避免重用变量,也避免变量重新赋值。

【讨论】:

    猜你喜欢
    • 2014-12-02
    • 2015-11-17
    • 2016-04-02
    • 2015-03-29
    • 2020-09-19
    • 1970-01-01
    • 2018-06-26
    • 1970-01-01
    • 2017-06-27
    相关资源
    最近更新 更多