如何读取文本文件中字符串数据的特定位置

时间:2012-06-26 17:03:16

标签: java file csv filereader

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

下面是一个样本记录。虽然这条线达到了一千行而且列数达到了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 个答案:

答案 0 :(得分: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();
    }
  }
}

这就是你想要的东西吗?

答案 1 :(得分: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]

答案 2 :(得分:1)

我认为CSV不是必须的,你是如何一行一行地阅读文件的? 我会一行一行,这样,读取每一行的内存并不昂贵(一次只有一行)。你可以在线上使用正则表达式,只使用你需要的组(使用Pattern和Matcher)来帮助提取你需要的东西。

答案 3 :(得分:0)

不要担心记忆;您可以将整个文件放在一个char数组中,而无需任何人注意。 CSV文件很痛苦,不会为您做任何事情。只需将每一行读入缓冲区 - 一个字符串,或字符串或字节数组 - 并从中获取所需内容;固定定位使其变得简单。

一般来说,在记忆和时间之间存在权衡。我发现大缓冲区,比如1​​00Kb超过1Mb,而不是10Kb,可以加速你5到10倍。 (如果重要的话,用各种尺寸自己测试。如果我理解你的话,你说的是40Kb,所以不需要比这更大的缓冲区。(如果它是40 Mega b那么做即使是一个40Mb的阵列也不会对你造成伤害,但现在你 开始浪费内存。))一定要关闭文件并释放对文件类的引用然后再去在做其他工作,所以你的缓冲区等不是内存泄漏。

相关问题