Java 在文件读取期间强制 IOException
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2566755/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Force IOException during file reading
提问by DixonD
I have a piece of code that reads data from a file. I want to force IOException in this code for testing purposes (I want to check if the code throws a correct custom exception in this case).
我有一段从文件中读取数据的代码。我想在此代码中强制 IOException 用于测试目的(我想检查代码在这种情况下是否抛出正确的自定义异常)。
Is there any way to create a file which is protected from being read, for example? Maybe dealing with some security checks can help?
例如,有什么方法可以创建一个防止被读取的文件?也许处理一些安全检查会有所帮助?
Please, note that passing the name of a non-existent file cannot help, because FileNotFoundException has a separate catch clause.
请注意,传递不存在文件的名称无济于事,因为 FileNotFoundException 有一个单独的 catch 子句。
Here is the piece of code for better understanding of the question:
这是为了更好地理解问题的一段代码:
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(csvFile));
String rawLine;
while ((rawLine = reader.readLine()) != null) {
// some work is done here
}
} catch (FileNotFoundException e) {
throw new SomeCustomException();
} catch (IOException e) {
throw new SomeCustomException();
} finally {
// close the input stream
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
// ignore
}
}
}
回答by Adam Batkin
You can always throw your own IOException
:
你总是可以扔你自己的IOException
:
throw new IOException("Test IOException");
回答by thelost
You could make this exception raise for a file that's too large.
您可以为过大的文件引发此异常。
回答by NG.
You could try creating the file as a superuser and then reading it as a standard user. There should be permissions issues there. Or just chmod the thing assuming you're on Linux. You can also try putting it in a hidden / protected directory.
您可以尝试以超级用户身份创建文件,然后以标准用户身份读取它。那里应该有权限问题。或者只是 chmod 假设你在 Linux 上的东西。您也可以尝试将其放在隐藏/受保护的目录中。
回答by Péter T?r?k
If you can refactor the code slightly to accept a Reader, rather than a filename, you can use mocks. With EasyMockyou can create a mock Reader, and set it to throw IOException upon calling any of its methods you wish. Then you just pass it to the method to be tested, and watch what happens :-)
如果您可以稍微重构代码以接受 Reader 而不是文件名,则可以使用模拟。使用EasyMock,您可以创建一个模拟 Reader,并将其设置为在调用任何您希望的方法时抛出 IOException。然后你只需将它传递给要测试的方法,然后观察会发生什么:-)
void readFile(Reader reader) throws SomeCustomException {
try {
String rawLine;
while ((rawLine = reader.readLine()) != null) {
// some work is done here
}
} catch (FileNotFoundException e) {
throw new SomeCustomException();
} catch (IOException e) {
throw new SomeCustomException();
} finally {
// close the input stream
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
// ignore
}
}
}
}
then the test code:
然后是测试代码:
mockReader = createMock(Reader.class);
expect(mockReader.readLine()).andThrow(
new IOException("Something terrible happened"));
replay(mockReader);
objectToTest.readFile(reader);
回答by jayshao
You can use a Mock library like Mockitoor Easymock (+classpath)to create a Mock file object (newer libs have classloader extensions that let you mock concrete classes like File), or can cooperate with something like PowerMock (see blog)and have a mock generated for the constructor call, and throw the appropriate exception when called.
您可以使用Mockito或Easymock(+classpath)之类的 Mock 库来创建 Mock 文件对象(较新的库具有类加载器扩展,可让您模拟 File 之类的具体类),或者可以与PowerMock 之类的东西合作(参见博客)并具有为构造函数调用生成模拟,并在调用时抛出适当的异常。
回答by Weston B
Disclaimer: I have not tested this on a non-Windows platform, so it may have different results on a platform with different file locking characteristics.
免责声明:我没有在非 Windows 平台上对此进行过测试,因此在具有不同文件锁定特性的平台上可能会有不同的结果。
If you lock the file beforehand, you can trigger an IOException when something attempts to read from it:
如果事先锁定文件,则可以在尝试读取文件时触发 IOException:
java.io.IOException: The process cannot access the file because another process has locked a portion of the file
This works even if you are in the same thread.
即使您在同一线程中,这也有效。
Here's some sample code:
这是一些示例代码:
final RandomAccessFile raFile = new RandomAccessFile(csvFile, "rw");
raFile.getChannel().lock();
回答by nsanzeri
You could force an exception by invoking the close method on your BufferedReader
:
您可以通过在您的 上调用 close 方法来强制异常BufferedReader
:
reader = new BufferedReader(new FileReader(csvFile));
// invoke the Close() method.
reader.Close();
String rawLine;
while ((rawLine = reader.readLine()) != null) {
// some work is done here
}
I hope that helps.
我希望这有帮助。
回答by River
I would recommend against using the FileNotFoundException. If you want to throw a specific exception for the file not existing, I would check csvFile.exists().
我建议不要使用 FileNotFoundException。如果你想为不存在的文件抛出一个特定的异常,我会检查 csvFile.exists()。
For example, you can make csvFilea directory. I tested your code and it threw:
例如,您可以将csvFile 设为目录。我测试了你的代码,它抛出了:
File file = new File("actually_a_directory.csv");
file.mkdir();
yourCode(file); // throws FileNotFoundException: "actually_a_directory.csv (Access is denied)"
File file = new File("actually_a_directory.csv");
file.mkdir();
yourCode(file); // throws FileNotFoundException: "actually_a_directory.csv (Access is denied)"
In my opinion, a file actually being a directory is not the same as FileNotFound, yet it acts the same in java.
在我看来,实际上是目录的文件与 FileNotFound 不同,但它在 java 中的作用相同。
回答by Jeroen Heemskerk
Define in your test an overloaded fileInputStream that throws an exception
在您的测试中定义一个引发异常的重载 fileInputStream
FileInputStream s;
try {
s = new FileInputStream(fileName) {
@Override
public int read() throws IOException {
throw new IOException("Expected as a test");
}
};
} catch (FileNotFoundException e) {
throw new RuntimeException(e.getMessage(), e);
}
回答by jjd
You can use for example Mockito to emulate that, however you would need to refactor your code so it were better testable. I would also advise to use try-with-resources if you use java 7+. Your code will look much cleaner.
例如,您可以使用 Mockito 来模拟它,但是您需要重构您的代码,以便更好地进行测试。如果您使用 java 7+,我还建议您使用 try-with-resources。你的代码看起来会干净很多。
You might extract the reader creation to a separate method so you could then replace an implementation with a mock. Like this
您可以将读取器创建提取到一个单独的方法中,这样您就可以用模拟替换实现。像这样
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class SomeClass {
public static final String IO_EXCEPTION = "IO Exception";
private String csvFile ="some_path";
public void someMethod() {
BufferedReader reader = null;
try {
reader = getReader();
String rawLine;
while ((rawLine = reader.readLine()) != null) {
// some work is done here
}
} catch (FileNotFoundException e) {
throw new SomeCustomException("FNF Exception");
} catch (IOException e) {
throw new SomeCustomException(IO_EXCEPTION);
} finally {
// close the input stream
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
// ignore
}
}
}
}
BufferedReader getReader() throws FileNotFoundException {
return new BufferedReader(new FileReader(csvFile));
}
class SomeCustomException extends RuntimeException {
public SomeCustomException(String message) {
super(message);
}
}
}
The test would look as following
测试将如下所示
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import SomeCustomException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
@RunWith(MockitoJUnitRunner.class)
public class SomeClassTest {
@Mock
private BufferedReader bufferedReader;
@Test
public void testMethod() throws IOException {
Mockito.when(bufferedReader.readLine()).thenThrow(new IOException());
SomeClass someClass = new SomeClass() {
@Override
BufferedReader getReader() throws FileNotFoundException {
return bufferedReader;
}
};
assertThatThrownBy(() -> someClass.someMethod()).isInstanceOf(SomeCustomException.class)
.hasMessage(SomeClass.IO_EXCEPTION);
}
}
This is how your someMethod might look like if you use try-with-resource
如果您使用 try-with-resource,这就是 someMethod 的样子
public void someMethod() {
try(BufferedReader reader = getReader()) {
String rawLine;
while ((rawLine = reader.readLine()) != null) {
// some work is done here
}
} catch (FileNotFoundException e) {
throw new SomeCustomException("FNF Exception");
} catch (IOException e) {
throw new SomeCustomException(IO_EXCEPTION);
}
}
2 times shorter 20 times more readable
缩短 2 倍 可读性提高 20 倍
PS as another option for the test, you might extend your SomeClass in the test class and override someMethod in the test class instead of creating an unanimous implementation. But I like the first option more. It is a matter of taste though.
PS 作为测试的另一个选项,您可以在测试类中扩展您的 SomeClass 并覆盖测试类中的 someMethod 而不是创建一致的实现。但我更喜欢第一个选项。虽然这是一个品味问题。
Hope that helps.
希望有帮助。
PPS: Just realized the question was asked years ago. :) Hopefully it helps somebody to find an answer these days.
PPS:刚刚意识到这个问题是多年前提出的。:) 希望这些天它可以帮助某人找到答案。