【问题标题】:Read 20gb text file with java [closed]用java读取20gb文本文件[关闭]
【发布时间】:2015-07-15 21:20:39
【问题描述】:

我有一个 20GB 的文本文件,我想读取它并将数据存储到数据库中。问题是当我尝试加载它之前它可以打印出任何东西以查看程序正在做什么它被终止,并且似乎它可能是由于文件的大小。如果有人对如何有效地阅读此文件有任何建议,请告诉我。

【问题讨论】:

  • 存储如何?作为一个blob?将其拆分为单独的字段/记录?
  • 听起来你正在尝试加载整个文件,然后才处理它。在内存中存储 20GB 不是正确的做法 - 逐行读取文件并存储它。您可以一次存储大量几行 - 但不能存储整个文件。
  • 是否有一个类可以将文件分成更小的块?这样就可以读取了。
  • Read large files in Java 的可能重复项

标签: java io java.util.scanner


【解决方案1】:

来自另一个帖子Read large files in Java

首先,如果您的文件包含二进制数据,那么使用 BufferedReader 将是一个很大的错误(因为您会将数据转换为字符串,这是不必要的,并且很容易损坏数据);您应该改用 BufferedInputStream 。如果它是文本数据并且您需要沿换行符拆分它,那么使用 BufferedReader 就可以(假设文件包含合理长度的行)。

关于内存,如果您使用大小合适的缓冲区应该没有任何问题(我会使用至少 1MB 来确保 HD 主要进行顺序读取和写入)。

如果速度成为问题,您可以查看 java.nio 包 - 据说这些包比 java.io 快,

至于将其读取到数据库中,请确保使用某种批量加载 API,否则将需要很长时间。

这是我用于 Netezza 的批量加载例程的示例......

    private static final void executeBulkLoad(
                    Connection connection, 
                    String schema,
                    String tableName,
                    File file,
                    String filename,
                    String encoding) throws SQLException   {

            String filePath = file.getAbsolutePath();
            String logFolderPath = filePath.replace(filename, "");

            String SQLString  = "INSERT INTO " + schema + "." + tableName + "\n";
            SQLString += "SELECT * FROM\n"; 
            SQLString += "EXTERNAL '" + filePath + "'\n";
            SQLString += "USING\n";
            SQLString += "(\n";
            SQLString += "    ENCODING '" + encoding + "'\n";
            SQLString += "    QUOTEDVALUE 'NO'\n";
            SQLString += "    FILLRECORD 'TRUE'\n";
            SQLString += "    NULLVALUE 'NULL'\n";
            SQLString += "    SKIPROWS 1\n";
            SQLString += "    DELIMITER '\\t'\n";
            SQLString += "    LOGDIR '" + logFolderPath + "'\n";
            SQLString += "    REMOTESOURCE 'JDBC'\n";
            SQLString += "    CTRLCHARS 'TRUE'\n";
            SQLString += "    IGNOREZERO 'TRUE'\n";
            SQLString += "    ESCAPECHAR '\\'\n";
            SQLString += ");";

            Statement statement = connection.createStatement();
            statement.execute(SQLString);
            statement.close();
    }       

【讨论】:

  • 您是否有任何资源可用于批量加载 api 或以前的问题可能会有所帮助?
【解决方案2】:

如果您需要将信息加载到数据库中,您可以使用Spring batch, 有了这个,您将读取您的文件,管理事务,对您的文件执行进程,将您的行保存到数据库中,控制您要执行提交的记录数量,我认为这是一个更好的选择,因为第一个问题是读取大文件,但您的下一个问题将是管理数据库的事务,控制提交等。我希望它对您有所帮助

【讨论】:

    【解决方案3】:

    如果您正在阅读非常大的文件,请始终使用 InputStreams。 例如

    BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
    String line = null;
    
    StringBuilder responseData = new StringBuilder();
    while((line = in.readLine()) != null) {
    // process line
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多