2

我正在处理一个包含多达一千行的文本文件。一个文本文件中有多个页眉和页脚。所以我不需要处理包含@h 和@f 的行。它告诉我事务的开始和结束(数据库事务,我将在一个事务中将这些记录保存到数据库)。

示例记录如下。尽管行数达到一千行,列数达到 40 列。从每一行我只寻找一个特定的数据,即(例如,我需要从位置 8 到 30 获取名称,从位置 60 到 67 等等)。这个位置可能是下一个空格或字符串之间。所以我不想将每一行的数据放入缓冲区/内存来处理它,因为我只对其中的几个感兴趣。CSV 文件是否允许从一行中的特定位置获取数据?我应该使用什么来获得更好的性能(在不占用太多内存的情况下尽快处理数据。)?我正在使用 Java

@h Header
@074VH01MATT    TARA   A5119812073921 RONG HI  DE BET IA76200  201108222   0500  *
@074VH01KAYT    DJ     A5119812073921 RONG DED CR BET IA71200  201108222   0500  *
@f Footer

@h Header
@074VH01MATT    TARA   A5119812073921 RONG HI  DE BET IA76200  201108222   0500  *
@074VH01KAYT    DJ     A5119812073921 RONG DED CR BET IA71200  201108222   0500  *
@f Footer
4

4 回答 4

5

这是我的解决方案:

import java.io.*;
class ReadAFileLineByLine 
{
 public static void main(String args[])
  {
  try{
    FileInputStream fstream = new FileInputStream("textfile.txt");
    BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
    String strLine;
    //Loop through and check if a header or footer line, if not
    //equate a substring to a temp variable and print it....
    while ((strLine = br.readLine()) != null)   {
      if (!(strLine.charAt(1) == "h" || strLine.charAt(1) == "f"))
        String tempName = strLine.substring(8,31);
      System.out.println(tempName);
    }
    //Close the input stream
    in.close();
  } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

你在找这样的东西吗?

于 2012-06-26T17:23:32.407 回答
4

使用BufferedReader,这样它就不会保存从InputStreamReader构造的内存中的所有内容,因此您可以指定字符集(正如FileReader的 JavaDoc所说的那样) - 我下面的示例使用UTF-8假设文件采用相同的编码。

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;

public class StringData {
    public static void main(String[] args) throws Exception {
        BufferedReader br = null;
        try {
            // change this value
            FileInputStream fis = new FileInputStream("/path/to/StringData.txt");
            br = new BufferedReader(new InputStreamReader(fis, "UTF-8"));
            String sCurrentLine;
            while ((sCurrentLine = br.readLine()) != null) {
                processLine(sCurrentLine);
            }
        } finally {
            if (br != null) br.close();
        }
    }

    public static void processLine(String line) {
        // skip header & footer
        if (line.startsWith("@h Header") || line.startsWith("@f Footer")) return;

        String name = line.substring(8, 22);
        String year = line.substring(63, 67);

        System.out.println("Name [" + name + "]\t Year [" + year +"]");
    }
}

输出

Name [MATT    TARA  ]    Year [2011] 
Name [KAYT    DJ    ]    Year [2011]
于 2012-06-26T17:56:56.497 回答
1

我认为 CSV 不是必须的,您如何逐行或一次全部读取文件?我会逐行进行,这样,读取每一行的内存成本并不高(一次只有一行)。您可以在线使用正则表达式并仅获取您需要的组(使用模式和匹配器)来帮助准确提取您需要的内容。

于 2012-06-26T17:15:38.557 回答
0

不用担心内存;您可以将整个文件放在一个 char 数组中,而不会引起任何人的注意。CSV 文件很麻烦,不会为您做任何事情。只需将每一行读入一个缓冲区——一个字符串、字符或字节数组——然后从中获取你需要的东西;固定的定位使它变得容易。

通常,内存和时间之间存在权衡。我发现大缓冲区,比如 100Kb 到超过 1Mb,而不是 10Kb,可以将你的速度提高 5 到 10 倍。(如果重要的话,用各种大小自行测试。如果我理解你的话,你说的是 40Kb,所以不需要比这更大的缓冲区。(如果它是 40 Mega b 然后进行测试。即使是 40Mb 阵列不会伤害你,但现在你开始浪费内存了。))在继续做其他工作之前,一定要关闭文件并释放对文件类的引用,这样你的缓冲区等就不是内存了泄漏。

于 2012-06-26T17:52:33.617 回答