当前位置: 首页 > 面试题库 >

从大文件中逐一读取3000万用户ID

华旭
2023-03-14
问题内容

我正在尝试使用Java读取非常大的文件。该大文件将具有这样的数据,这意味着每行将具有一个用户ID。

149905320
1165665384
66969324
886633368
1145241312
286585320
1008665352

在那个大文件中,将有大约3000万用户ID。现在,我只尝试一次从该大文件中一次读取所有用户ID。意味着每个用户ID只能从该大文件中选择一次。例如,如果我有3000万用户ID,那么使用多线程代码只能打印3000万用户ID。

下面是我拥有的代码,它是一个运行10个线程的多线程代码,但是使用下面的程序,我无法确保每个用户ID仅被选择一次。

public class ReadingFile {


    public static void main(String[] args) {

        // create thread pool with given size
        ExecutorService service = Executors.newFixedThreadPool(10);

        for (int i = 0; i < 10; i++) {
            service.submit(new FileTask());
        }
    }
}

class FileTask implements Runnable {

    @Override
    public void run() {

        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader("D:/abc.txt"));
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
                //do things with line
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                br.close();
            } catch (IOException e) {

                e.printStackTrace();
            }
        }
    }
}

有人可以帮我吗?我在做什么错?最快的方法是什么?


问题答案:

假设您没有做过像跨多个磁盘分割文件这样的事情,那么让一个线程按顺序读取文件确实不能改善。使用一个线程,您可以执行一次查找,然后进行长时间的顺序读取。如果有多个线程,则每个线程都将获得对磁盘头的控制权时,它们将导致多个寻道。

编辑:这是一种在仍然使用串行I /
O读取行的同时并行处理行的方法。它使用BlockingQueue在线程之间进行通信。的FileTask增加线到队列,并且CPUTask读取它们并对其进行处理。这是一个线程安全的数据结构,因此无需向其添加任何同步。您正在使用put(E e)将字符串添加到队列中的方法,因此,如果队列已满(最多可容纳200个字符串,如中的声明中所定义),则会阻塞ReadingFile这些FileTask块,直到空间释放为止。同样,您正在使用take()从队列中删除项目的方法,因此CPUTaskwill会阻塞,直到有项目可用为止。

public class ReadingFile {
    public static void main(String[] args) {

        final int threadCount = 10;

        // BlockingQueue with a capacity of 200
        BlockingQueue<String> queue = new ArrayBlockingQueue<>(200);

        // create thread pool with given size
        ExecutorService service = Executors.newFixedThreadPool(threadCount);

        for (int i = 0; i < (threadCount - 1); i++) {
            service.submit(new CPUTask(queue));
        }

        // Wait til FileTask completes
        service.submit(new FileTask(queue)).get();

        service.shutdownNow();  // interrupt CPUTasks

        // Wait til CPUTasks terminate
        service.awaitTermination(365, TimeUnit.DAYS);

    }
}

class FileTask implements Runnable {

    private final BlockingQueue<String> queue;

    public FileTask(BlockingQueue<String> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader("D:/abc.txt"));
            String line;
            while ((line = br.readLine()) != null) {
                // block if the queue is full
                queue.put(line);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

class CPUTask implements Runnable {

    private final BlockingQueue<String> queue;

    public CPUTask(BlockingQueue<String> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        String line;
        while(true) {
            try {
                // block if the queue is empty
                line = queue.take(); 
                // do things with line
            } catch (InterruptedException ex) {
                break; // FileTask has completed
            }
        }
        // poll() returns null if the queue is empty
        while((line = queue.poll()) != null) {
            // do things with line;
        }
    }
}


 类似资料:
  • 我想逐行读取一个文件,但不完全加载到内存中。 我的文件太大,无法在内存中打开,如果尝试这样做,我总是会出现内存错误。 文件大小为1 GB。

  • 问题内容: 我想遍历整个文件的每一行。一种方法是读取整个文件,将其保存到列表中,然后遍历感兴趣的行。此方法占用大量内存,因此我正在寻找替代方法。 到目前为止,我的代码: 执行此代码将显示错误消息:。 有什么建议么? 目的是计算成对的字符串相似度,这意味着对于文件中的每一行,我要计算每隔一行的距离。 问题答案: 正确的,完全Python的读取文件的方法如下: 该with语句处理文件的打开和关闭,包括

  • 问题内容: 我在S3中有一个csv文件,我正在尝试读取标题行以获取大小(这些文件是由我们的用户创建的,因此它们几乎可以是任何大小)。有没有办法使用boto做到这一点?我以为也许我们可以使用python BufferedReader,但是我不知道如何从S3键打开流。任何建议都很好。谢谢! 问题答案: 看来boto具有可以执行此操作的功能。这是一些对我有用的代码: 调用会从对象返回下一个n个字节。 当

  • 问题内容: 我想逐个读取文件。该文件分为几部分,分别存储在不同类型的媒体上。我目前要做的是调用文件的每个单独部分,然后将其合并回原始文件。 问题是我需要等到所有块都到达后才能播放/打开文件。是否有可能在块到达时读取块,而不是等待它们全部到达。 我正在处理媒体文件(电影文件)。 问题答案: 您要的是源数据线。当数据太大而无法一次将其保存在内存中时,这是完美的选择,因此您可以在接收整个文件之前开始播放

  • 在我的项目中,我需要使用以下库(OMPL)。我特别感兴趣的是一个成员函数printAsMatrix(std::ofstream&out),它将数据输出到终端或文件。这里的函数是: 但我需要这些输出的值在其原始形式,作为双倍。因此,我想通过库阅读它们,使用我自己实现的以下函数: 由于函数只接受std::ifstream数据,我得到了很多编译错误。 所以我做了一个临时的变通办法: > 创建了新的变量:

  • 问题内容: 我需要使用Java逐行读取大约5-6 GB的大型文本文件。 我如何快速做到这一点? 问题答案: 常见的模式是使用 如果你假设没有字符编码,则可以更快地读取数据。例如ASCII-7,但差别不大。你处理数据的时间很可能会花费更长的时间。 一种不太常用的模式,可以避免line泄漏的范围。 在Java 8中,你可以执行