Friday, August 7, 2015

Java IO system 8.7



I/O
JDK1.4Java.nio.*包中引入了新的JavaI/O类库,其目的在于提高速度。而速度的提高来自于所使用的结构更接近于操作系统执行I/O的方式:通道和缓冲器
我们可以把它想象成一个煤矿,通道是一个包含煤层(数据)的矿藏,而缓冲器则是派送到矿藏的卡车。卡车载满煤炭而归,我们再从卡车上获得煤炭。也就是说,我们并没有直接和通道交互,我们只是和缓冲器交互,并把缓冲器派送回通道。通道要么从缓冲器获取数据,要么向缓冲器发送数据。
唯一直接与通道交互的缓冲器是ByteBuffer——也就是说,可以存储未加工字节的缓冲器。它是相当基础的类:通过告知分配多少存储空间来创建一个ByteBuffer对象,并且还有一个方法选择集,用于以原始的字节形式或基本数据类型输出和读取数据。但是,没办法输出或读取对象,包括字符串对象。这种处理虽然很低级,却也正好。因为这是大多数操作系统中更有效的映射方式。
I/O类库中有三个类被修改了,用以产生FileChannel。这三个被修改的类是FileInputStreamFileOutputStream以及用于既读又写的RandomAccessFile

1. 通道是一种相当基础的东西:可以向它传送用于读写的ByteBuffer,并且可以锁定文件的某些区域用于独占式访问。
2. 将字节存放于ByteBuffer的方法之一是用put直接填充。也可以使用wrap()方法将已存在的字节数据包装到ByteBuffer中。一旦如此,就不能复制底层的数组,而是将它作为所产生的ByteBuffer的存储器(没太理解这句话?)。
3. 一旦调用read()来告知FileChannelByteBuffer存储字节,就必须调用缓冲器上的flip(),让它做好让别人读取字节的准备(这似乎有一点拙劣,但是却适用于获取最大速度)。如果我们打算使用缓冲器执行进一步的read操作,我们也必须调用clear()来为每个read()做好准备。

脑洞read() Returns the number of bytes read, possibly zero, or -1 if the channel has reached end-of-stream是以int形式返回下一字节,所以while (in.read(buffer)!= -1) {…}
           readline() Returns a String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached 返回的是字符串, 所以while ((s = br.readLine())!= null) {…}

4. clear()操作是对所有的内部指针重新安排,以便缓冲器在另一个read()操作期间能够做好接收数据的准备。
5. 特殊方法transferTo()transferFrom()则允许我们将一个通道和另一个通道直接相连。

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/ }
这才对了。

Monday, August 3, 2015

[转载]https和http区别


转载自网站:  http://network.51cto.com/art/201502/465280.htm
仅用于个人学习~

=======================================================
总的来说,http效率更高,https安全性更高。

首先谈谈什么是HTTPS:
HTTPS(Secure Hypertext Transfer Protocol)安全超文本传输协议 它是一个安全通信通道,它基于HTTP开发,用于在客户计算机和服务器之间交换信息。它使用安全套接字层(SSL)进行信息交换,简单来说它是HTTP的 安全版。 它是由Netscape开发并内置于其浏览器中,用于对数据进行压缩和解压操作,并返回网络上传送回的结果。HTTPS实际上应用了Netscape的安 全全套接字层(SSL)作为HTTP应用层的子层。(HTTPS使用端口443,而不是象HTTP那样使用端口80来和TCP/IP进行通信。)SSL使 用40 位关键字作为RC4流加密算法,这对于商业信息的加密是合适的。HTTPS和SSL支持使用X.509数字认证,如果需要的话用户可以确认发送者是谁。
HTTPS和HTTP的区别:
https协议需要到ca申请证书,一般免费证书很少,需要交费。 http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议 http和https使用的是完全不同的连接方式用的端口也不一样,前者是80,后者是443。 http的连接很简单,是无状态的 HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议 要比http协议安全 HTTPS解决的问题: 1 . 信任主机的问题. 采用https 的server 必须从CA 申请一个用于证明服务器用途类型的证书. 改证书只有用于对应的server 的时候,客户度才信任次主机. 所以目前所有的银行系统网站,关键部分应用都是https 的. 客户通过信任该证书,从而信任了该主机. 其实这样做效率很低,但是银行更侧重安全. 这一点对我们没有任何意义,我们的server ,采用的证书不管自己issue 还是从公众的地方issue, 客户端都是自己人,所以我们也就肯定信任该server. 2 . 通讯过程中的数据的泄密和被窜改 1. 一般意义上的https, 就是 server 有一个证书. a) 主要目的是保证server 就是他声称的server. 这个跟第一点一样. b) 服务端和客户端之间的所有通讯,都是加密的. i. 具体讲,是客户端产生一个对称的密钥,通过server 的证书来交换密钥. 一般意义上的握手过程. ii. 加下来所有的信息往来就都是加密的. 第三方即使截获,也没有任何意义.因为他没有密钥. 当然窜改也就没有什么意义了. 2. 少许对客户端有要求的情况下,会要求客户端也必须有一个证书. a) 这里客户端证书,其实就类似表示个人信息的时候,除了用户名/密码, 还有一个CA 认证过的身份. 应为个人证书一般来说上别人无法模拟的,所有这样能够更深的确认自己的身份. b) 目前少数个人银行的专业版是这种做法,具体证书可能是拿U盘作为一个备份的载体.像我用的交通银行的网上银行就是采取的这种方式。 HTTPS 一定是繁琐的. a) 本来简单的http协议,一个get一个response. 由于https 要还密钥和确认加密算法的需要.单握手就需要6/7 个往返. i. 任何应用中,过多的round trip 肯定影响性能. b) 接下来才是具体的http协议,每一次响应或者请求, 都要求客户端和服务端对会话的内容做加密/解密. i. 尽管对称加密/解密效率比较高,可是仍然要消耗过多的CPU,为此有专门的SSL 芯片. 如果CPU 信能比较低的话,肯定会降低性能,从而不能serve 更多的请求.
符:SSL的简介:
SSL是Netscape公司所提出的安全保密协议,在浏览器(如Internet Explorer、Netscape Navigator)和Web服务器(如Netscape的Netscape Enterprise Server、ColdFusion Server等等)之间构造安全通道来进行数据传输,SSL运行在TCP/IP层之上、应用层之下,为应用程序提供加密数据通道,它采用了RC4、MD5 以及RSA等加密算法,使用40 位的密钥,适用于商业信息的加密。同时,Netscape公司相应开发了HTTPS协议并内置于其浏览器中,HTTPS实际上就是SSL over HTTP,它使用默认端口443,而不是像HTTP那样使用端口80来和TCP/IP进行通信。HTTPS协议使用SSL在发送方把原始数据进行加密,然 后在接受方进行解密,加密和解密需要发送方和接受方通过交换共知的密钥来实现,因此,所传送的数据不容易被网络黑客截获和解密。 然而,加密和解密过程需要耗费系统大量的开销,严重降低机器的性能,相关测试数据表明使用HTTPS协议传输数据的工作效率只有使用HTTP协议传输的十 分之一。假如为了安全保密,将一个网站所有的Web应用都启用SSL技术来加密,并使用HTTPS协议进行传输,那么该网站的性能和效率将会大大降低,而 且没有这个必要,因为一般来说并不是所有数据都要求那么高的安全保密级别,所以,我们只需对那些涉及机密数据的交互处理使用HTTPS协议,这样就做到鱼 与熊掌兼得。总之不需要用https 的地方,就尽量不要用。