【问题标题】:Java read URLConnection with many lines efficientlyJava 高效读取多行 URLConnection
【发布时间】:2016-06-01 12:02:03
【问题描述】:

我必须读取一个 URLConnection 响应,其中包含 2MB 的 Java 中漂亮打印的 JSON。

2mb 不是“小”,但绝不是大。它包含 JSON。然而,它是漂亮的打印 JSON,大约有 60k 行。一个

while ((line = bufferedReader.readLine()) != null) {
    lineAllOfIt += line;
}

阅读此回复大约需要 10 分钟。我的方法一定有问题,但我想不出更好的方法。

【问题讨论】:

  • 我假设你的意思是 MB,否则你的文件会很小,只有 2 毫比特:P
  • lineAllOfIt += line; 是“错误的”,因为字符串是不可变的,并且您会一遍又一遍地创建大小不断增加的新字符串。使用字符串生成器或像stackoverflow.com/a/37079572/995891 那样做
  • 你要写答案吗?这是解决方案
  • 你想用你的 JSON 做什么?解析它没有?
  • 我不认为即使在 StringBuilder 中将 2 Mo 的文件加载到内存中也是一个好主意,除非您只执行一次并且此操作不能并行完成,否则您会填满你的堆

标签: java service get request urlconnection


【解决方案1】:

对于这种特殊情况,我会使用 java 在本地缓存文件,您可以将文件传输到计算机的内存不足,然后您可以逐行浏览它,而无需将文件也加载到内存中并拉出您需要的数据或一次加载所有数据。

编辑:对变量名进行了更改我从我的代码中提取了这个并忘记了中和变量。 FileChannel transferTo/transferFrom 也可以更有效,因为副本可能更少,并且取决于操作可能来自 SocketBuffer -> Disk。 FileChannel API

    String urlString = "http://update.domain.com/file.json" // File URL Path
    Path diskSaveLocation = Paths.get("file.json"); // This will be just help place it in your working directory

    final URL url = new URL(fileUrlString);
    final URLConnection conn = url.openConnection();
    final long fileLength = conn.getContentLength();
    System.out.println(String.format("Downloading file... %s, Size: %d bytes.", fileUrlString, fileLength));
    try(
            FileOutputStream stream = new FileOutputStream(diskSaveLocation.toFile(), false);
            FileChannel fileChannel = stream.getChannel();
            ReadableByteChannel inChannel = Channels.newChannel(conn.getInputStream());
    ) {
        long read = 0;
        long readerPosition = 0;
        while ((read = fileChannel.transferFrom(inChannel, readerPosition, fileLength)) >= 0 && readerPosition < fileLength) {
            readerPosition += read;
        }
        if (fileLength != Files.size(diskSaveLocation)) {
            Files.delete(diskSaveLocation);
            System.out.println(String.format("File... %s did not download correctly, deleting file artifact!", fileUrlString));
        }
    }
    System.out.println(String.format("File Download... %s completed!", fileUrlString));
    ((HttpURLConnection) conn).disconnect();

您现在可以使用 NIO2 方法读取同一文件,该方法允许您逐行读取而无需加载到内存中。使用 Scanner 或 RandomAccessFile 方法可以防止将行读入堆。如果您想读取整个文件,也可以使用 Javas Files 实用程序方法中的许多方法从缓存文件中本地读取。

Java Read Large Text File With 70million line of text

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-19
    • 1970-01-01
    • 1970-01-01
    • 2016-06-05
    • 1970-01-01
    • 2021-11-01
    • 2011-01-26
    • 2011-03-14
    相关资源
    最近更新 更多