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