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

回到顶部