2、文件IO
public class MessyCode { public static void main(String[] args) throws Exception {
init();
wrong();
right1();
right2();
right3();
}
private static void init() throws Exception {
Files.deleteIfExists(Paths.get("hello.txt"));
Files.write(Paths.get("hello.txt"), "你好Hi".getBytes(Charset.forName("GBK")));
System.out.println(HexBin.encode(Files.readAllBytes(Paths.get("hello.txt"))).toUpperCase());
}
private static void wrong() throws Exception {
char[] chars = new char[10];
String content = "";
// 测试机器默认编码时UTF-8
System.out.println("current machine charset: " + Charset.defaultCharset());
// FileReader默认是以当前机器的默认字符集来读取文件的
try (FileReader fileReader = new FileReader("hello.txt")) {
int count;
while ((count = fileReader.read(chars)) != -1) {
content = new String(chars, 0, count);
}
}
// 有乱码
System.out.println("result: " + content);
}
private static void right1() throws Exception {
char[] chars = new char[10];
String content = "";
// 如果希望指定字符集的话, 需要直接使用InputStreamReader和FileInputStream
try (FileInputStream fis = new FileInputStream("hello.txt");
InputStreamReader isr = new InputStreamReader(fis, Charset.forName("GBK"))) {
int count;
while ((count = isr.read(chars)) != -1) {
content += new String(chars, 0, count);
}
}
// 无乱码
System.out.println("result is: " + content);
}
private static void right2() throws Exception{
// 读取超出内存的大文件时会OOM, readAllLines读取文件所有内容之后放到List<String>返回, 如果内存无法容纳这个List, 就会OOM
String result = Files.readAllLines(Paths.get("hello.txt"),
Charset.forName("GBK")).stream().findFirst().orElse("");
System.out.println("result is: " + result);
}
private static void right3() throws Exception{
// Files.lines返回Stream<String>, 可以按需消费, 可以避免OOM
// 但是对于Files类一些返回Stream的方法没有释放资源, 如没有释放文件句柄
Files.lines(Paths.get("hello.txt"), Charset.forName("GBK"))
.collect(Collectors.toList()).forEach(System.out::println);
}
}
public class ResourceNeedClose { public static void main(String[] args) throws Exception {
init();
wrong();
right();
}
/**
* 随便写入10行数据到一个demo.txt文件中
*/
private static void init() throws Exception {
Files.write(Paths.get("demo.txt"),
IntStream.rangeClosed(1, 10).mapToObj(i -> UUID.randomUUID().toString())
.collect(Collectors.toList()),
UTF_8, CREATE, TRUNCATE_EXISTING);
}
/**
* 然后使用Files.lines方法读取这个文件100万次, 每读取一行计数器 +1
* <p>
* 会报错, too many open files
*/
private static void wrong() {
LongAdder longAdder = new LongAdder();
IntStream.rangeClosed(1, 1000000).forEach(i -> {
try {
Files.lines(Paths.get("demo.txt")).forEach(line -> longAdder.increment());
} catch (IOException e) {
e.printStackTrace();
}
});
System.out.println("total: " + longAdder.longValue());
}
private static void right() {
LongAdder longAdder = new LongAdder();
IntStream.rangeClosed(1, 1000000).forEach(i -> {
// 使用try-with-resources方式, 确保流的close方法可以调用释放资源
try (Stream<String> lines = Files.lines(Paths.get("demo.txt"))) {
lines.forEach(line -> longAdder.increment());
} catch (IOException e) {
e.printStackTrace();
}
});
System.out.println("total: " + longAdder.longValue());
}
/**
* 更高性能的文件复制
*
* 参考: https://developer.ibm.com/articles/j-zerocopy/
*
* 在一些操作系统(比如高版本的Linux和UNIX)上可以实现DMA(直接内存访问),
* 也就是数据从磁盘经过总线直接发送到目标文件,无需经过内存和CPU进行数据中转
*/
private static void fileChannelOperation() throws IOException {
FileChannel in = FileChannel.open(Paths.get("src.txt"), READ);
FileChannel out = FileChannel.open(Paths.get("dest.txt"), CREATE, WRITE);
in.transferTo(0, in.size(), out);
}
}
以上是 2、文件IO 的全部内容, 来源链接: utcz.com/z/517586.html