【问题标题】:Java IO Exception: Negative seek offsetJava IO 异常:负寻道偏移
【发布时间】:2015-07-24 19:58:56
【问题描述】:

我有一个程序来替换文件中的内容。但是会导致IO Exception,不知道逻辑哪里出错了?

代码如下:

import java.io.File;
import java.io.RandomAccessFile;

public class Test
{
   public static void main(String args[]) throws Exception
   {
        File f = new File("test.txt");
        replaceAll(f, "hello world", "my world");
   }

       public static void replaceAll(File file, String oldText, String newText) throws Exception
    {
        int[] indices = findAllIndices(file, oldText);
        if(indices.length > 0)
        {
            for(int i=0;i<indices.length;i++)
            {
                replace(file, oldText, newText);
            }
        }
    }

        public static int[] findAllIndices(File file, String text) throws Exception
    {
        int[] indices;
        int index = -1, count = 0, i=0;
        String givenText = FileUtils.readFileToString(file);
        index = givenText.indexOf(text);
        while(index >= 0)
        {
            count++;
            index = givenText.indexOf(text, index+1);
        }
        indices = new int[count];
        index = givenText.indexOf(text);
        while(index >= 0)
        {
            indices[i] = index;
            index = givenText.indexOf(text, index+1);
            i++;
        }
        return indices;
    }

        public static void replace(File file, String oldText, String newText) throws Exception
    {        
        int index = findFirstIndex(file, oldText);
        if(index >=0)
        {
            RandomAccessFile raf = new RandomAccessFile(file, "rw");
            raf.seek(new Integer(index).byteValue());
            String emptyString = fixedLengthString(" ", oldText.length());
            raf.write(emptyString.getBytes());
            raf.seek(new Integer(index).byteValue());            
            raf.write(newText.getBytes());
        }
    }    
}

MWE 是大代码的一部分。原始代码的堆栈跟踪是:

Exception in thread "main" java.io.IOException: Negative seek offset
    at java.io.RandomAccessFile.seek(RandomAccessFile.java:538)
    at org.javaextensions.FindAndReplace.replace(FindAndReplace.java:51)
    at org.javaextensions.FindAndReplace.replaceAll(FindAndReplace.java:76)
    at Test.main(Test.java:16)
Java Result: 1

【问题讨论】:

  • 你能发布堆栈跟踪吗?
  • @TomJonckheere 请查看编辑
  • raf.seek(new Integer(index).byteValue()) 中 index 的值是多少?什么时候抛出异常?我认为它是负面的......这会引发 I/O 异常

标签: java seek


【解决方案1】:
    public static void replace(File file, String oldText, String newText) throws Exception
{        
    int index = findFirstIndex(file, oldText);
    if(index >=0)
    {
        RandomAccessFile raf = new RandomAccessFile(file, "rw");
        raf.seek(new Integer(index).byteValue());

你的问题要么在这里^^

        String emptyString = fixedLengthString(" ", oldText.length());
        raf.write(emptyString.getBytes());
        raf.seek(new Integer(index).byteValue());

您应该检查 Integer(index.byteValue()) 的值,它可能返回一个负数。另外,我不知道您为什么要将其转换为一个字节,也不知道您为什么要先创建一个 Integer 对象。两者都不是必需的

【讨论】:

  • 我已经添加了一个答案。请检查
【解决方案2】:

问题在于您为搜索生成偏移量的方式:

    if(index >=0) {
        ...
        raf.seek(new Integer(index).byteValue());
    }

你从一个非负数(很好)的索引开始......

然后你将索引转换为byte

问题在于 Java 字节在 -128 到 +127 的范围内。所以最有可能发生的是你的正整数被转换成一个负字节值......然后又变成一个负整数。例如,int 130 映射到 byte -126,然后又映射回 int -126

我完全不明白您将索引转换为字节的原因,但如果您试图将索引值“减少”为 0 到 255 范围内的数字,那么您应该这样做:

        raf.seek(index & 0xff);

【讨论】:

    【解决方案3】:

    即使您正在检查索引 >= 0,您也没有考虑索引 > 127 的情况:

        if(index >=0)
        {
            ...
            raf.seek(new Integer(index).byteValue());
            ...
        }
    

    字节的范围是 -128 到 127。如果你取 128 到 256 之间的任何 int 并尝试获取 byteValue(),你将不会得到大于零的数字。
    试试看:

        int i = 127;
        byte b = new Integer(i).byteValue();
        System.out.println("Value of b = " + b);
    

    这导致 b = 127。 用 i = 128 试试,你会得到 b = -128。

    • 1 - 127 大于零。
    • 128 - 256 小于或等于零。
    • 257 - 383 大于零。 ...等等。

    【讨论】:

      【解决方案4】:

      我不确定您为什么要再次重塑索引值。见下文,您的代码包含这些索引的数组:

      int[] indices = findAllIndices(file, oldText);
      

      您可以在调用替换方法时将其作为附加参数传递。

      要实施的代码更改:

      public static void replaceAll(File file, String oldText, String newText) throws Exception
      {
          int[] indices = findAllIndices(file, oldText);
      
          for(int i=0;i<indices.length;i++)
              replace(file, oldText, newText, indices[i]);
      }
      
      public static void replace(File file, String oldText, String newText, int index) throws Exception
      {
          RandomAccessFile raf = new RandomAccessFile(file, "rw");
          ..
          ..
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-05-18
        • 2018-11-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-18
        • 1970-01-01
        相关资源
        最近更新 更多