Thursday, August 6, 2015

Java IO system 8.6



1.当我们使用DataOutputStream时,写字符串并且让DataOutputStream能够恢复它的唯一可靠的做法就是使用UTF-8编码(writeUTF()readUTF())
         UTF-8是一种多字节格式,其编码长度根据实际使用的字符集会有所变化。如果我们使用的只是ASCII或者几乎都是ASCII字符(只占7位),那么就显得极其浪费空间和带宽,所以UTF-8ASCII字符编码成单一字节的形式,而非ASCII字符则编码成两到三个字节的形式。

         为了保证所有的读方法都能正常工作,我们必须自动流中数据项所在的确切位置,因为极有可能将保存的double数据作为一个简单的字节序列char或其他类型读入。因此,我们必须:要么为文件中的数据采用固定的格式,要么将额外的信息保存到文件中,以便能够对其进行解析以确定数据的存放位置。P544

         2. RandomAccessFile
         RandomAccessFile拥有读取基本类型和UTF-8字符串的各种具体方法。在使用它时,你必须自动文件排版,这样才能正确地操作它。
seek() 可在文件中到处移动,可用于修改文件中的某个值。
    public static void main(String[] args) throws IOException {
        java.io.RandomAccessFile rf = new java.io.RandomAccessFile(file, "rw");
        for (int i = 0; i < 7; i++) {
            rf.writeDouble(i*1.414);
        }
        rf.writeUTF("The end of the file");
        rf.close();
        display();
        rf = new java.io.RandomAccessFile(file, "rw");
        rf.seek(5*8);
        rf.writeDouble(47.0001);
        rf.close();
        display();
    }
我们看到示例中rf.seek(5*8),因为double总是8字节长,所以用seek来查找第五个双精度值,就是5*8
我的问题是:seek方法是搜索后听到第五个值的末尾吗?


3.管道流
用于任务之间的通信,它们的价值只有再我们开始理解多线程以后才会显现。

4. java.util.TreeSet.headSet()
public SortedSet<E> headSet(E toElement)
参数toElement-- 这是返回集合的高点(不包括)
        TreeSet<String> words = new TreeSet<String>(new TextFile("TextFile.java","\\W+"));
        // Display the capitalized words:
        System.out.println(words.headSet("a"));
//        System.out.println(words);
此例子的输出:
System.out.println(words)
System.out.println(words.headSet("a"));
[0, ArrayList, Arrays, Break, BufferedReader, Display, File, FileReader, IOException, Normally, PrintWriter, Read, Regular, RuntimeErrorException, RuntimeException, Simple, String, StringBuilder, System, TextFile, TreeSet, W, Write, a, an, any, append, args, as, asList, at, by, call, capitalized,…]
[0, ArrayList, Arrays, Break, BufferedReader, Display, File, FileReader, IOException, Normally, PrintWriter, Read, Regular, RuntimeErrorException, RuntimeException, Simple, String, StringBuilder, System, TextFile, TreeSet, W, Write]
   显而易见,输出了所有小于a的部分。

         5.readLine的过程中会把换行符去掉,因此要记得为每行把换行符加上。
         6.在任何打开文件的代码中,作为防卫措施都在finally子句中添加了对文件close()的调用,以保证文件将会被正确关闭。
疑问: Redirecting的例子中,为什么BufferedInputStream in = new BufferedInputStream(new FileInputStream("Redirecting.java")); 不像PrintStream out = new PrintStream(new BufferedOutputStream(new FileOutputStream("test.out"))); 添加close();语句呢。

我尝试了一下不添加out.close(),结果是输出了一个0kB的文件,是没写上吗?




标准I/O
1.           回显你的输入
    public static void main(String[] args) throws IOException {
        BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
        String s;
        while ((s = stdin.readLine())!=null && s.length()!=0) {
            System.out.println(s);
        }  // An empty line or Ctrl-Z terminate the program
    }

2.           标准I/O重定向
如果我们突然开始在显示器上创建大量输出,而这些输出滚动得太快以至于无法阅读时,重定向输出就显得很有用。(第22章展示了一种更方便的解决方案:一个GUI程序,具有带滚动的文本区域)
对于我们想重复测试某个特定用户的输入序列的命令行程序来说,重定向输入就很有价值。



进程控制
当你需要在Java内部执行其他操作系统的程序,并且要控制这些程序的输入和输出时。一项常见的任务是运行程序,并将产生的输出发送到控制台。
1.       OSExecute
    public static void main(String[] args) {
        OSExecute.command("javap OSExecuteDemo");
}
这个程序一直报错,
Working Directory: ${workspace_loc:helloworld/src/from/eighteen}
Error:  class not found: from.eighteen.OSExecuteDemo
Exception in thread "main" mine.tools.OSExecuteException: Errors executing javap from.eighteen.OSExecuteDemo
         at mine.tools.OSExecute.command(OSExecute.java:33)
         at from.eighteen.OSExecuteDemo.main(OSExecuteDemo.java:8)

看了网上的评论:Javap works against the .class bytecode. So point the classpath at the VariablesTestProject/out or whatever.
于是把Working Directory ${workspace_loc:helloworld/bin/from/eighteen}
还是报warning
Compiled from "OSExecuteDemo.java"
public class from.eighteen.OSExecuteDemo {
  public from.eighteen.OSExecuteDemo();
  public static void main(java.lang.String[]);
}
Warning: Binary file OSExecuteDemo contains from.eighteen.OSExecuteDemo
Exception in thread "main" mine.tools.OSExecuteException: Errors executing javap OSExecuteDemo
         at mine.tools.OSExecute.command(OSExecute.java:33)
         at from.eighteen.OSExecuteDemo.main(OSExecuteDemo.java:8)
         最后我把代码改成了:
    public static void main(String[] args) {
        OSExecute.command("javap from.eighteen.OSExecuteDemo");
    }
于是把Working Directory ${workspace_loc:helloworld/bin/ }
这才对了。

No comments:

Post a Comment