简而言之Java.io:22个案例研究

这篇文章试图涵盖java.io中的一整套操作。 与与此主题相关的其他书籍和博客相比,我的动机是通过案例研究展示“操作方法”。 作为一名Java的学生,我意识到学习一种新的程序语言的最有效方法是通过示例:复制并粘贴一段代码,运行它以查看结果,然后尝试逐步修改并重新运行它。 。 因此,我认为这篇文章会有所帮助。

值得注意的是,本文不会涉及与java.nio相关的任何内容,因为我认为这是一个完全不同的主题。

目录

情况0:创建一个新文件

import java.io.File;
public class FileOperationTest {
  public static void main(String[] args) {
    File f = new File("helloworld.txt");
    try {
      f.createNewFile();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

输出: 如果之前没有“ helloword.txt”,则在工作目录中创建一个新的空文件。

情况1:File中的两个常量

import java.io.File;
public class FileOperationTest {
  public static void main(String[] args) {
    System.out.println(File.separator);
    System.out.println(File.pathSeparator);
  }
}

输出:

/
:

我得到上面的输出,因为我正在Linux上工作。 如果使用Windows,则输出应为\; 。 可以看出,出于可移植性和鲁棒性的目的,应始终建议使用这两个常量。

情况2:删除文件

import java.io.File;
public class FileOperationTest {
  public static void main(String[] args) {
    File f = new File("helloworld.txt");
    if (f.exists()) {
      if (!f.delete()) {
        System.out.println("the file cannot be deleted.");
      }
    } else {
      System.out.println("the file does not exist.");
    }
  }
}

情况3:创建目录

import java.io.File;
public class FileOperationTest {
  public static void main(String[] args) {
    File f = new File("hello");
    f.mkdir();
  }
}

情况4:列出给定目录中的文件和目录

import java.io.File;
public class FileOperationTest {
  public static void main(String[] args) {
    File f = new File(".");
    for (String str : f.list()) {
      System.out.println(str);
    }
  }
}

输出:我正在使用Eclipse

.settings
.classpath
.project
src
bin

文件 list()返回一个字符串数组。 如果您更喜欢File的数组,请使用FilelistFiles()

import java.io.File;
public class FileOperationTest {
  public static void main(String[] args) {
    File f = new File(".");
    for (File subFile : f.listFiles()) {
      System.out.println(subFile.getName());
    }
  }
}

情况5:测试文件是否为文件

import java.io.File;
public class FileOperationTest {
  public static void main(String[] args) {
    File f = new File("helloworld.txt");
    if (f.isFile()) {
      System.out.println("YES");
    } else {
      System.out.println("NO");
    }
  }
}

File结合。 listFiles() ,我们可以列出给定目录及其子目录中的所有文件。

import java.io.File;

public class FileOperationTest {

  public static void main(String[] args) {
    File f = new File(".");
    listFiles(f);
  }

  private static void listFiles(File f) {
    if (f.isFile()) {
      System.out.println(f.getName());
      return;
    }
    for (File subFile : f.listFiles()) {
      listFiles(subFile);
    }
  }
}

输出:案例4进行比较以查看差异

org.eclipse.jdt.core.prefs
.classpath
.project
FileOperationTest.java
FileOperationTest.class

情况6:写入RandomAccessFile

import java.io.IOException;
import java.io.RandomAccessFile;

public class FileOperationTest {

  public static void main(String[] args)
      throws IOException {
    RandomAccessFile file = new RandomAccessFile(
        "helloworld.txt", "rw");
    file.writeBytes("hello world!");
    file.writeChar('A');
    file.writeInt(1);
    file.writeBoolean(true);
    file.writeFloat(1.0f);
    file.writeDouble(1.0);
    file.close();
  }
}

如果使用文本编辑器打开文件,则会发现乱码,除了第一个hello world!A (请注意,在“ hello world!”末尾的char A )。 这是因为RandomAccessFile仅在文件中写入字节数组。

情况7:将字节写入文件

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class FileOperationTest {

  public static void main(String[] args)
      throws IOException {
    OutputStream out = new FileOutputStream(
        "helloworld.txt");
    String str = "hello world!";
    out.write(str.getBytes());
    out.close();
  }
}

这次您可以看到“你好,世界!” 在文件中。 当然,您可以逐字节写入OutputStream ,但是效率较低:

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class FileOperationTest {

  public static void main(String[] args)
      throws IOException {
    OutputStream out = new FileOutputStream(
        "helloworld.txt");
    String str = "hello world!";
    for (byte b : str.getBytes()) {
      out.write(b);
    }
    out.close();
  }
}

情况8:将字节追加到文件

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class FileOperationTest {

  public static void main(String[] args)
      throws IOException {
    OutputStream out = new FileOutputStream(
        "helloworld.txt", true);
    String str = "hello world!";
    out.write(str.getBytes());
    out.close();
  }
}

输出: hello world!hello world!

情况9:从文件读取字节

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class FileOperationTest {

  public static void main(String[] args)
      throws IOException {
    InputStream in = new FileInputStream("helloworld.txt");
    byte[] bs = new byte[1024];
    int len = -1;
    while ((len = in.read(bs)) != -1) {
      System.out.println(new String(bs, 0, len));
    }
    in.close();
  }
}

InputStream 如果到达文件末尾, read()将返回-1。 否则,它将返回读入缓冲区的字节总数。

情况10:复制文件

简单地结合案例79 ,我们将获得复制功能。

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class Copy {

  public static void main(String[] args)
      throws IOException {
    if (args.length != 2) {
      System.out.println("java Copy SOURCE DEST");
      System.exit(1);
    }
    InputStream input = new FileInputStream(args[0]);
    OutputStream output = new FileOutputStream(args[1]);
    int len = 0;
    byte bs[] = new byte[1024];
    while ((len = input.read(bs)) != -1) {
      output.write(bs, 0, len);
    }
    input.close();
    output.close();
  }
}

情况11:将字符写入文件

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class FileOperationTest {

  public static void main(String[] args)
      throws IOException {
    Writer out = new FileWriter("helloworld.txt");
    String str = "hello world!";
    out.write(str);
    out.close();
  }
}

对于上述情况,您将获得与案例7相同的结果。 那么区别是什么呢? FileWriter用于编写字符流。 它将使用默认的字符编码和默认的字节缓冲区大小。 换句话说,为方便起见,它是FileOutputStream的包装器类。 因此,要自己指定这些值,请考虑使用FileOutputStream

情况12:从文件中读取字符

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class FileOperationTest {

  public static void main(String[] args)
      throws IOException {
    Reader in = new FileReader("helloworld.txt");
    char cs[] = new char[1024];
    int len = -1;
    while ((len = in.read(cs)) != -1) {
      System.out.println(new String(cs, 0, len));
    }
    in.close();
  }
}

是否使用字节流或字符流? 真的要看 两者都有缓冲区。 InputStream / OutputStream提供了更大的灵活性,但会使您的“简单”程序变得复杂。 另一方面,FileWriter / FileReader提供了一个整洁的解决方案,但是您失去了控制权。

情况13:从OutputStream转换为FileWriter

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;

public class FileOperationTest {

  public static void main(String[] args)
      throws IOException {
    Writer out = new OutputStreamWriter(
        new FileOutputStream("helloworld.txt"));
    out.write("hello world!");
    out.close();
  }
}

您可以指定字符集,而不是使用默认字符编码。 例如,

Writer out = new OutputStreamWriter(
        new FileOutputStream("helloworld.txt"), "utf8");

情况14:从InputStream转换为FileReader

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;

public class FileOperationTest {

  public static void main(String[] args)
      throws IOException {
    Reader in = new InputStreamReader(
        new FileInputStream("helloworld.txt"));
    char cs[] = new char[1024];
    int len = -1;
    while ((len = in.read(cs)) != -1) {
      System.out.println(new String(cs, 0, len));
    }
    in.close();
  }
}

案例15:使用管道

以下代码创建了两个线程,一个生产者在一端将内容写入管道,而另一个消费者从另一端从管道读取该线程。 要创建管道,我们需要分别创建PipedInputStreamPipedOutputStream ,并使用output.connect(input)或通过其构造函数进行连接。 在此程序中,我有意先启动Consumer线程,并在启动Producer线程之前让整个程序休眠1秒。 这将显示管道确实起作用。 值得注意的是,我关闭了Producer中的管道,因为“ 写入流的线程应始终在终止之前关闭OutputStream。 ”如果我们删除out.close()行,将抛出IOException

java.io.IOException: Write end dead
    at java.io.PipedInputStream.read(PipedInputStream.java:311)
    at java.io.PipedInputStream.read(PipedInputStream.java:378)
    at java.io.InputStream.read(InputStream.java:101)
    at foo.Consumer.run(FileOperationTest.java:58)
    at java.lang.Thread.run(Thread.java:701)
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

public class FileOperationTest {

  public static void main(String[] args)
      throws IOException, InterruptedException {

    PipedInputStream input = new PipedInputStream();
    PipedOutputStream output = new PipedOutputStream();
    output.connect(input);

    Producer producer = new Producer(output);
    Consumer consumer = new Consumer(input);
    new Thread(consumer).start();
    Thread.sleep(1000);
    new Thread(producer).start();
  }
}

class Producer implements Runnable {

  private final OutputStream out;

  public Producer(OutputStream out) {
    this.out = out;
  }

  @Override
  public void run() {
    String str = "hello world!";
    try {
      out.write(str.getBytes());
      out.flush();
      out.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

class Consumer implements Runnable {

  private final InputStream in;

  public Consumer(InputStream in) {
    this.in = in;
  }

  @Override
  public void run() {
    byte[] bs = new byte[1024];
    int len = -1;
    try {
      while ((len = in.read(bs)) != -1) {
        System.out.println(new String(bs, 0, len));
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

情况16:将格式化的字符串写入文件

PrintStream添加了一些功能,可以方便地打印各种数据值的表示形式。 格式字符串的语法与C几乎相同。

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;

public class FileOperationTest {

  public static void main(String[] args)
      throws IOException {
    PrintStream print = new PrintStream(
        new FileOutputStream("helloworld.txt"));
    print.printf("%s %s!", "hello", "world");
    print.close();
  }
}

案例17:重定向“标准” IO

在Java中,标准输出和错误输出均为PrintStream 。 标准输入是InputStream 。 因此,我们可以自由地重新分配它们。 以下代码将标准输出重定向到错误输出。

public class FileOperationTest {
  public static void main(String[] args) {
    System.out.println("hello world!");
    System.setOut(System.err);
    System.out.println("hello world!");
  }
}

输出:在Eclipse中,红色文本表示错误消息

hello world!hello world!

情况18:逐行读取文件

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class FileOperationTest {

  public static void main(String[] args)
      throws IOException {
    BufferedReader reader = new BufferedReader(
        new FileReader("helloworld.txt"));
    String str = null;
    while ((str = reader.readLine()) != null) {
      System.out.println(str);
    }
    reader.close();
  }
}

案例19:压缩到一个zip文件

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class FileOperationTest {

  public static void main(String[] args)
      throws IOException {
    ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(
        "helloworld.zip"));
    String str = "hello world!";
    for (int i = 0; i < 3; i++) {
      zipOut.putNextEntry(new ZipEntry("helloworld" + i + ".txt"));
      zipOut.write(str.getBytes());
      zipOut.closeEntry();
    }
    zipOut.close();
  }
}

上面的代码创建了一个zip文件,并放置了三个文件,分别名为“ helloworld0.txt”,“ helloworld1.txt”和“ helloworld2.txt”,每个文件都包含内容“ hello world!”。

案例20:从zip文件中提取

import java.io.FileInputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class FileOperationTest {

  public static void main(String[] args)
      throws IOException {
    ZipInputStream zipIn = new ZipInputStream(new FileInputStream(
        "helloworld.zip"));
    ZipEntry entry = null;
    byte bs[] = new byte[1024];
    while ((entry = zipIn.getNextEntry()) != null) {
      // get file name
      System.out.printf("file: %s content: ", entry.getName());
      int len = -1;
      // read current entry to the buffer
      while((len=zipIn.read(bs)) != -1) {
        System.out.print(new String(bs, 0, len));
      }
      System.out.println();
    }
    zipIn.close();
  }
}

输出:

file: helloworld0.txt content: hello world!
file: helloworld1.txt content: hello world!
file: helloworld2.txt content: hello world!

情况21:推回字节

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.PushbackInputStream;

public class FileOperationTest {

  public static void main(String[] args)
      throws IOException {
    PushbackInputStream push = new PushbackInputStream(
        new ByteArrayInputStream("hello, world!".getBytes()));
    int temp = 0;
    while ((temp = push.read()) != -1) {
      if (temp == ',') {
        push.unread('.');
      }
      System.out.print((char) temp);
    }
  }
}

上面的代码在读取逗号后按了一个点,因此输出为

hello,. world!

但是,如果您尝试向后推更多字符,例如push.unread("(...)".getBytes()); ,您将获得IOException :推回缓冲区已满。 这是因为推回缓冲区的默认大小为1。要指定更大的容量,请使用构造函数PushbackInputStream(InputStream in, int size) ,例如

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.PushbackInputStream;

public class FileOperationTest {

  public static void main(String[] args)
      throws IOException {
    PushbackInputStream push = new PushbackInputStream(
        new ByteArrayInputStream("hello, world!".getBytes()), 10);
    int temp = 0;
    while ((temp = push.read()) != -1) {
      if (temp == ',') {
        push.unread("(...)".getBytes());
      }
      System.out.print((char) temp);
    }
  }
}

输出:

hello,(...) world!

参考: 简而言之 Java.io:PGuru博客上来自我们的JCG合作伙伴 Peng Yifan的 22个案例研究

翻译自: https://www.javacodegeeks.com/2013/12/java-io-in-nutshell-22-case-studies.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值