Java 文件高级技术(一):常见文件类型处理

  1. 字节流和字符流都是以流的方式读写文件,流的限制有?
    答:

    • 要么读,要么写,不能同时读和写
    • 不能随机读写,只能从头读到尾,且不能重复读,虽然通过缓冲可以实现部分重读,但是有限制。
  2. RandomAccessFile 的作用?
    答:RandomAccessFile 没有上面两个限制,既可以读,也可以写,还可以随机读写,是一个更接近操作系统 API 的封装类。

  3. 内存映射文件的作用?
    答:内存映射文件可以高效处理非常大的文件,而且可以被多个不同的应用程序共享,特别适合用于不同应用程序之间的通信

  4. 序列化的作用是?
    答:使用流读写文件时,需要逐个处理对象中的每个字段,处理起来较为麻烦、需要考虑很多空格或特殊字符等小细节。

  5. Java 中经常处理的常见的文件类型有哪些?
    答:

    • 属性文件:属性文件是常见的配置文件,用于在不改变代码的情况下改变程序的行为。
      * CSVCSVComma-Separated Values 的缩写,表示逗号分隔值,是一种非常常见的文件类型。大部分日志文件都是 CSVCSV 也经常用于交换表格类型的数据。CSV 看上去很简单,但处理的复杂性经常被低估。
    • Excel:在编程中,经常需要将表格类型的数据导出为 Excel 格式,以方便用户查看,也经常需要接受 Excel 类型的文件作为输入以批量导入数据。
    • HTML:所有网页都是 HTML 格式,我们经常需要分析 HTML 网页,以从中提取感兴趣的信息。
    • 压缩文件:压缩文件有多种格式,也有很多压缩工具,大部分情况下,我们可以借助工具而不需要自己写程序处理压缩文件,但某些情况下,需要自己编程压缩文件或解压缩文件。
  6. 【笔试题】使用类 java.util.Properties 读取配置文件 config.properties

    1
    2
    3
    4
    db.host = 192.168.10.100
    db.port = 3306
    db.username = zhangsan
    db.password = mima1234
答:

1
2
3
4
Properties prop = new Properties();
prop.load(new FileInputStream("config.properties")); // load() 用于从流中加载属性
String host = prop.getProperty("db.host");
int port = Integer.valueOf(prop.getProperty("db.port", "3306")); // getProperty() 用于获取属性,可以提供一个默认值,如果没有找到配置的值,就返回默认值
  1. 使用类 Properties 处理属性文件的好处和限制分别是?
    答:

    • 可以自动处理空格,分隔符 = 前后的空格会被自动忽略。
    • 可以自动忽略空行。
    • 可以添加注释,以字符 #! 开头的行会被视为注释,进行忽略。
    • 限制:不能直接处理中文,在配置文件中,所有非 ASCII 字符需要使用 Unicode 编码。
  2. CSV 文件是指?
    答:

    • CSVComma-Separated Values 的缩写,表示逗号分隔值
    • 一般而言,一行表示一条记录,一条记录包含多个字段,字段之间用逗号分隔。
    • 一般而言,分隔符不一定是逗号,可能是其他字符,如 tab\t、冒号 :、分号 ; 等。
    • 程序中的各种日志文件通常是 CSV 文件,在导入导出表格类型的数据时,CSV 也是常用的一种格式。
  3. CSV 文件处理的复杂性?
    答:

    • 字段内容中包含分隔符
    • 字段内容中包含换行符
    • 怎么表示 null 值。
    • 空行和字段之间的空格怎么处理。
    • 怎么表示注释
  4. 使用第三方类库 Apache Commons CSV 读取 CSV 文件的示例(CSV 1.4 版本)?
    答:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    CSVFormat format = CSVFormat.newFormat(';').withQuote('"').withNullString("N/A").withIgnoreSurroundingSpaces(true);
    Reader reader = new FileReader("student.csv");
    try {
    for(CSVRecord record : format.parse(reader)) {
    int fieldNum = record.size();
    for(int i=0; i<fieldNum; i++) {
    System.out.print(record.get(i) + " ");
    }
    System.out.println();
    }
    } finally {
    reader.close();
    }
  1. 使用第三方类库 Apache Commons CSVCSV 文件?
    答:

    1
    2
    3
    4
    5
    6
    7
    8
    CSVPrinter out = new CSVPrinter(new FileWriter("student.csv), CSVFormat.DEFAULT);
    out.printRecord("老马", 18, "看电影,看书,听音乐");
    out.printRecord("小马", 16, "乐高;赛车;");
    out.close();

    // 输出文件 student.csv 中的内容为:
    “老马”, 18, “看电影,看书,听音乐”
    “小马”, 16, “乐高;赛车;”
  1. Java 中怎样处理 Excel 文件?
    答:

    • Excel 主要有两种格式,扩展名分别为 .xls.xlsx.xlsxOffice 2007 以后的 Excel 文件的默认扩展名。
    • Java 中处理 Excel 文件及其他微软文档广泛使用 POI 类库。
  2. 保存学生列表到 student.xlsPOI 3.15 版本)?
    答:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // Workbook: 表示一个 Excel 文件对象,它是一个接口,有两个主要类 HSSFWorkbook 和 XSSFWorkbook,前者对应 .xls 格式,后者对应 .xlsx 格式
    // Sheet: 表示一个工作表
    // Row: 表示一行
    // Cell: 表示一个单元格
    public static void saveAsExcel(List<Student> list) throws IOException {
    Workbook wb = new HSSFWorkbook();
    Sheet sheet = wb.createSheet();
    for(int i=0; i<list.size(); i++) {
    Student student = list.get(i);
    Row row = sheet.createRow(i);
    row.createCell(0).setCellValue(student.getName());
    row.createCell(1).setCellValue(student.getAge());
    row.createCell(2).setCellValue(student.getScore());
    }
    OutputStream out = new FileOutputStream("student.xls);
    wb.write(out);
    out.close();
    wb.close();
    }

    // 如果要保存为 .xlsx 格式,只需要替换第一行为:
    Workbook wb = new XSSFWorkbook();
  1. 使用 POI 解析 Excel 文件?
    答:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public static List<Student> readAsExcel() throws Exception {
    Workbook wb = WorkbookFactory.create(new File("student.xls"));
    List<Student> list = new ArrayList<Student> ();
    for(Sheet sheet : wb) {
    for(Row row : sheet) {
    String name = row.getCell(0).getStringCellValue();
    int age = (int) row.getCell(1).getNumericCellValue();
    double score = row.getCell(2).getNumericCelValue();
    list.add(new Student(name, age, score));
    }
    }
    wb.close();
    return list;
    }
  2. 使用 HTML 分析器 jsoup 分析网址:http://www.cnblogs.com/swiftma/p/5631311.htmlHTML 代码,抽取网页主题内容中每篇文章的标题和链接?
    答:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    Document doc = Jsoup.parse(new File("articles.html"), "UTF-8);
    Elements elements = doc.select("#cnblogs_post_body p a");
    for(Element e : elements) {
    String title = e.text();
    String href = e.attr("href");
    System.out.println(title + ", " + href);
    }

    // 输出为(部分):
    计算机程序的思维逻辑(1)- 数据和变量,http://www.cnblogs.com/swiftma/p/5396551.html
    计算机程序的思维逻辑(2)- 赋值,http://www.cnblogs.com/swiftma/p/5399315.html

    // jsoup 也可以直接连接 URL 进行分析,比如,上面代码的第一行可以替换为:
    String url = "http://www.cnblogs.com/swifma/p/5631311.html";
    Document doc = Jsoup.connect(url).get();
  3. Java 对压缩文件的支持?
    答:

    • 压缩文件有多种格式,Java SDK 支持两种:gzipzip
    • gzip 只能压缩一个文件,zip 可以压缩多个文件
    • 对于 gzipjava.util.zip.GZIPOutputStreamjava.util.zip.GZIPInputStream 分别是 OutputStreamInputStream 的子类,都是装饰类。GZIPOutputStream 加到已有的流上,就可以是实现压缩;GZIPInputStream 加到已有的流上,就可以实现解压缩。
    • 对于 zipjava.util.zip.ZipOutputStreamjava.util.zip.ZipInputStream 也分别是 OutputStreamInputStream 的子类,也都是装饰类。使用起来比 gzip 要麻烦些。
  4. 压缩一个文件?
    答:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public static void gzip(String fileName) throws IOException {
    InputStream in = null;
    String gzipFileName = fileName + ".gz";
    OutputStream out = null;
    try {
    in = new BufferedInputStream(new FileInputStream(fileName));
    out = new GZIPOutputStream(new BufferedOutputStream(new FileOutputStream(gzipFileName)));
    copy(in, out); // 复制输入流的内容到输出流
    } finally {
    if(out != null) {
    out.close();
    }
    if(in != null) {
    in.close();
    }
    }
    }
  1. 解压一个文件?
    答:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public static void gUnzip(String gzipFileName, String unzipFileName) throws IOException {
    InputStream in = null;
    OutputStream out = null;
    try {
    in = new GZIPInputStream(new BufferedInputStream(new FileInputStream(gzipFileName)));
    out = new BufferedOutputStream(new FileOutputStream(unzipFileName));
    copy(in, out);
    } finally {
    if(out != null) {
    out.close();
    }
    if(in != null) {
    in.close();
    }
    }
    }