【问题标题】:Add up numbers in files将文件中的数字相加
【发布时间】:2015-06-10 00:49:42
【问题描述】:

我有一个包含很多文件(约 40,000 个)的目录,每个文件正好有两行,每行都有一个数字。我想将整个目录中的所有数字相加;我如何快速有效地做到这一点?

我试过这个,但它不起作用,我一生都无法弄清楚为什么。我得到一个 NullPointerException,但它不应该是,因为我猜是 listOfFiles.length 导致它。

package me.counter;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;

public class TicTacToeCounter {
    static String dir = "./data/";
    public static void main(String args[]) throws IOException{
        int total = 0;
        File folder = new File(dir);
        File[] listOfFiles = folder.listFiles();

            for (int i = 0; i < listOfFiles.length; i++) {
                total += getWins(listOfFiles[i].getAbsolutePath());
                total += getLosses(listOfFiles[i].getAbsolutePath());
            }

            System.out.println(total);
    }

    public static int getWins(String move) throws IOException{
        File f = new File(move);
        if(!f.exists()){
            f.createNewFile();
            PrintWriter writer = new PrintWriter(move, "UTF-8");
            writer.println("0");
            writer.println("0");
            writer.close();
            return 0; 
        }
        Scanner fscanner = new Scanner(f);
        int wins = 0;
        if(fscanner.hasNext())
            wins = fscanner.nextInt();
        fscanner.close();
        return wins;
    }

    public static int getLosses(String move) throws IOException{
        File f = new File(move);
        if(!f.exists()){
            f.createNewFile();
            PrintWriter writer = new PrintWriter(move, "UTF-8");
            writer.println("0");
            writer.println("0");
            writer.close();
            return 0; 
        }
        Scanner fscanner = new Scanner(f);
        fscanner.nextInt();
        int losses = 0; 
        if(fscanner.hasNext())
            losses = fscanner.nextInt();
        fscanner.close();
        return losses;
    }
}

【问题讨论】:

  • 尝试一下。如果您有具体问题,请发布您的尝试并编辑您的问题。
  • @paisanco 我添加了我的代码
  • I'm guessing that the listOfFiles.length:你不需要猜测。请发布您的确切错误消息以及完整的堆栈跟踪,包括行号,我们会确定的。
  • @sstan 我收到一条消息说错误来自第 15 行,这也是 listOfFiles.length 所在的位置。

标签: java file add


【解决方案1】:

这正是您所需要的。 它将动态检查所有文件,您无需提供文件数量。 例如,如果您有任意数量的文件和每个文件中不同数量的行,请不要担心。它会正确读取。

import java.io.*;
import java.util.*;
import java.text.*;

public class TicTacToeCounter
{
    //arraylist that will read and hold all file names that can be used later in the program.
    public ArrayList<String> fileList = new ArrayList<String>();
    //arraylist of all lines from all files.
    ArrayList<Integer> theData = new ArrayList<Integer>();

    //class constructor
    public TicTacToeCounter() throws Exception
    {
        //provide the directory name here where you have those 40000 files.
        //I have testdata directory in my program in the same folder where my .java and .class file resides.
        File folder = new File("testdata");
        File[] listOfFiles = folder.listFiles();
        ArrayList<String> tempData = new ArrayList<String>();

        for (int i = 0; i < listOfFiles.length; i++)
        {
            if (listOfFiles[i].isFile())
            {
                fileList.add(listOfFiles[i].getName());
            }
            else if (listOfFiles[i].isDirectory())
            {
                System.out.println("Directory " + listOfFiles[i].getName());
            }
        }

        //for every filename in fileList, do....
        for (String s : fileList)
        {
            //call readFile method and pass file name as a variable s. add objects to tempData arraylist.
            tempData = readFile(s);
            //for every line in tempData, do....
            for (String line : tempData)
            {
                //add the line in theData arraylist, also convert into Integer before adding.
                theData.add(Integer.parseInt(line));
            }
        }

        //for every object in theData arraylist, print the object. alternatevely you can print it in previous stage.
        for (Integer s : theData)
        {
            System.out.println(s);
        }
    }

    //readFile method that will read our data files.
    public ArrayList<String> readFile(String fileName) throws Exception
    {
        ArrayList<String> data = new ArrayList<String>();
        //don't forget to add directory name here as we are only passing filename, not directory.
        BufferedReader in = new BufferedReader(new FileReader("testdata/"+fileName));

        String temp = in.readLine(); 
        while (temp != null)
        {
            data.add(temp);
            temp = in.readLine(); 
        }
        in.close();
        return data;
    }
}

【讨论】:

  • 这对我不起作用,我仍然在第 22 行收到 NullPointerException
  • 确保您的数据文件没有损坏或没有任何空行等(最后检查)。从少量具有您可以跟踪的准确数据的文件开始。然后再添加一些并每次检查以确保代码正常工作。
  • 或者,在继续编写代码之前使用“while (variable != null)”。要找出需要在哪里使用 while 循环,请使用调试器。
【解决方案2】:

堆栈跟踪应该告诉您错误发生的确切位置,您不必猜测。请检查:该目录存在并且它是一个目录,并且您的 listOfFiles 不为空,然后再对其进行长度处理。

folder.exists() && folder.isDirectory() {
   \\ you might want to check if folder.canRead() and folder.canWrite()
   \\ get listOfFiles
}

if (listOfFiles != null) { // proceed with operations

P.S: 你的 getWins 和 getLosses 也可以改进。我可能会尝试读取一次文件(如果这些文件不存在,则创建,如果你必须,但正如@sstan 提到的,你刚刚从目录中获取了文件名,没有理由不应该存在它)并阅读如果文件中始终只有 2 行,则输赢。现在,如果它不存在,您正在创建一个,然后读取您刚刚创建的那个,我们不必这样做。

【讨论】:

  • 我什至不明白为什么 OP 会检查文件是否存在。该文件必须存在,因为他是通过调用File.listFiles() 获得的。
  • 是的,你是对的。我也不知道。可能有人在我们得到列表之后和阅读之前删除了文件。我只是假设这是他们需要做的一些要求的一部分。
【解决方案3】:

不要使用数组作为文件,而是使用 ArrayList。让您了解错误发生的原因更加方便和透明。而且,如果您使用数组,则必须在启动它时定义一个长度,而您的情况还没有这样做。

【讨论】:

  • 这并没有真正改变任何东西;这是更好的做法,但实际上并不能让它发挥作用。
  • 它当然不会改变任何东西,但 ArrayLists 更容易处理,我猜。无论如何,上面提供了arraylist的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多