【问题标题】:How to know offset of a begining of a line in text file in java?如何知道java文本文件中行首的偏移量?
【发布时间】:2013-02-09 21:51:16
【问题描述】:

我想知道文本文件中每一行的偏移量。

目前我已经尝试过了,

path=FileSystems.getDefault().getPath(".",filename);
br=Files.newBufferedReader(path_doc_title_index_path, Charset.defaultCharset());
int offset=0; //offset of first line.       
String strline=br.readline();
offset+=strline.length()+1; //offset of second line

通过这种方式,我可以遍历整个文件以了解整个文本文件中行首的偏移量。但是,如果我使用RandomAccessFile 来查找文件并使用上述方法计算的偏移量访问一行,那么我发现自己处于某行的中间。那就是好像offset不正确。

怎么了?这种方法计算偏移量是否不正确?请问有更好更快的方法吗?

【问题讨论】:

  • Charset.defaultCharset()也是文件使用的字符集吗?您使用的是 Windows 还是 Linux?不要添加1,而是尝试添加System.getProperty("line.separator").length()
  • 我正在使用 linux。不知道字符集请指导我。
  • 在创建BufferedReader 时,您必须指定正在读取的文件的编码。你给了Charset.defaultCharset()。如果您的文件是UTF-8 编码的,则需要指定Charset.forName("UTF-8")System.getProperty("line.separator").length() 在您的系统上的评估结果是什么?
  • System.getProperty("line.separator").length() 计算结果为 1。

标签: java text-files offset


【解决方案1】:

您的代码仅适用于 ASCII 编码文本。由于某些字符需要超过一个字节,因此您必须更改以下行

offset += strline.length() + 1;

offset += strline.getBytes(Charset.defaultCharset()).length + 1;

正如我在您问题下方的 cmets 中所述,您必须指定文件的正确编码。例如。 Charset.forName("UTF-8") 此处以及您初始化 BufferedReader 的位置。

【讨论】:

  • 谢谢。我会尽力回复。
  • 还有一个问题。如何在linux中确定文件的文本编码??
  • 谢谢。在我的情况下,它提供text/plain; charset=us-ascii 作为输出。这意味着默认字符集是 us-ascii。是依赖操作系统还是使用 java 它总是 us-ascii??
  • @TheCrazyProgrammer:不,这不是默认字符集。这是您指定的文件的字符集。默认字符集取决于操作系统,但对于 Linux,您可以随意配置。
【解决方案2】:

显然,这给了我预期的结果。在下面的程序中,我通过一组通过 BufferedReader 收集的偏移量打印出文件的每一行。这是你的情况吗?

public static void main(String[] args) {
    File readFile = new File("/your/file/here");
    BufferedReader reader = null;
    try
    {
        reader = new BufferedReader( new FileReader(readFile) );
    }
    catch (IOException ioe)
    {
        System.err.println("Error: " + ioe.getMessage());     
    }
    List<Integer> offsets=new ArrayList<Integer>(); //offset of first line.       
    String strline;
    try {
        strline = reader.readLine();
        while(strline!=null){
            offsets.add(strline.length()+System.getProperty("line.separator").length()); //offset of second line
            strline = reader.readLine();
        }
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    try {
        RandomAccessFile raf = new RandomAccessFile(readFile, "rw");
        for(Integer offset : offsets){
            try {
                raf.seek(offset);
                System.out.println(raf.readLine());
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }   
}

【讨论】:

  • 仅适用于仅包含一个字节字符的文件。
  • 谢谢@jlordo,你是对的。正如您所指出的,如果不是这种情况,则必须指定正确的编码...
  • 即使您指定了正确的编码,也不能使用strline.length(),因为字符中的长度可能与文件中实际字节的长度不同。有关更多信息,请参阅我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-13
  • 2013-07-14
  • 2014-04-03
  • 1970-01-01
  • 2012-03-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多