`

【转-汇总】IO流基础知识及Socket 流传输乱码的问题

阅读更多

如下部分,摘自http://www.iteye.com/topic/313635,写的太好了。收藏已经不够爽了。

什么是流:

 

流是一个抽象的概念。当Java程序需要从数据源读取数据时,会开启一个到数据源的流。数据源可以是文件,内存或者网络等。同样,当程序需要输出数据到目的地时也一样会开启一个流,数据目的地也可以是文件、内存或者网络等。流的创建是为了更方便地处理数据的输入输出。

 

流分为字节流和字符流。字节流也称为原始数据,需要用户读入后进行相应的编码转换。而字节流的实现是基于自动转换的,读取数据时会把数据按照JVM的默认编码自动转换成字符。

 

字节流由InputStream和OutputStream处理,而字符流由Reader和Writer处理。Reader和Writer是Java后加入的处理类,出于让数据的处理更方便的目的。

 

字节流处理概述:

 

对于字节流处理的类都继承自InputStream和OutputStream这两个抽象类。

 

InputStream提供的最重要的方法是:

 

Java代码   收藏代码
  1. read();  
  2. read(byte[] b) ;  
  3. read(byte[] b, int off, int len) ;  

 

用于从输入流中读取字节。

 

OutputStream提供的最重要的方法是:

 

Java代码   收藏代码
  1. write(int b);  
  2. write(byte[] b);  
  3. write(byte[] b, int off, int len)   

 

用于将字节写入输出流。

 

字节流处理类概述:

 

字节流的处理类有很多,他们都继承自InputStream或者OutputStream抽象类。

 

输入流:

 

先谈谈输入流,输入流中跟数据源直接接触的类有:FileInputStream和ByteArrayInputStream,他们分别实现了从文件或者内存中的字节数组读入数据到输入流。

 

其他的输入流处理类都是装饰类(Decorator模式),下面对他们进行一下简单介绍:

 

BufferedInputStream: 提供了缓冲功能。

DataInputStream: 允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。

PipedInputStream: 允许以管道的方式来处理流。当连接到一个PipedOutputStream后,它会读取后者输出到管道的数据。

PushbackInputStream: 允许放回已经读取的数据。

SequenceInputStream: 能对多个inputstream进行顺序处理。

 

输出流:

 

基本上每个输入流类都有一个相应的输出流类,提供相应的输出流处理。

同样,跟数据目的地直接接触的类有:FileOutputStream和ByteArrayOutputStream,前者实现了把数据流写入文件的功能,后者实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray()  toString() 获取数据。

 

下面对其它的装饰类做一下简单介绍:

BufferedOutputStream: 提供了缓冲功能的输出流,在写出完成之前要调用flush来保证数据的输出。

DataOutputStream: 数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入。

PipedOutputStream: 允许以管道的方式来处理流。可以将管道输出流连接到管道输入流来创建通信管道。管道输出流是管道的发送端。通常,数据由某个线程写入 PipedOutputStream 对象,并由其他线程从连接的 PipedInputStream 读取。

PrintStream: 为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。我们经常用到的System.out或者System.err都是PrintStream。

 

字符流处理概述:

 

所有的字符流操作类都继承自Reader或者Writer这两个抽象类。

 

Reader提供的重要方法有:

 

Java代码   收藏代码
  1. read(char[] cbuf);  
  2. read(char[] cbuf, int off, int len);  
  3. read(CharBuffer target);  

 

他们提供了从流中读取数据到字符数组或者CharBuffer的功能。

 

Writer提供的重要方法有:

 

Java代码   收藏代码
  1. write(char[] cbuf);  
  2. write(char[] cbuf, int off, int len);  
  3. write(int c);  
  4. write(String str);  
  5. write(String str, int off, int len);  

 

他们提供了把字符、字符数组或者字符串写入流中的功能。

 

字符流处理类概述:

 

输入流:

 

跟数据源直接接触的类:

CharArrayReader: 从内存中的字符数组中读入数据,以对数据进行流式读取。

StringReader:从内存中的字符串读入数据,以对数据进行流式读取。

FileReader:从文件中读入数据。注意这里读入数据时会根据JVM的默认编码对数据进行内转换,而不能指定使用的编码。所以当文件使用的编码不是JVM默认编码时,不要使用这种方式。要正确地转码,使用InputStreamReader。

 

装饰类:

BufferedReader:提供缓冲功能,可以读取行:readLine();

LineNumberReader: 提供读取行的控制:getLineNumber()等方法。

InputStreamReader: 字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。

 

输出流:

 

根数据目的相关的类:

CharArrayWriter:把内存中的字符数组写入输出流,输出流的缓冲区会自动增加大小。输出流的数据可以通过一些方法重新获取。

StringWriter: 一个字符流,可以用其回收在字符串缓冲区中的输出来构造字符串。

FileWriter:把数据写入文件。

 

装饰类:

BufferedWriter:提供缓冲功能。

OutputStreamWriter:字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。

PrintWriter: 向文本输出流打印对象的格式化表示形式。

 

流处理中的其它方法:

 

mark和reset用于重复读取某段的数据,如下代码:

 

Java代码   收藏代码
  1. is = new BufferedInputStream(new FileInputStream("res/input.data"));  
  2. assertTrue(is.available() > 0);  
  3. assertTrue(is.markSupported());  
  4.   
  5. // The read limit has no effect.  
  6. is.mark(0);  
  7.   
  8. int first = is.read();  
  9. int second = is.read();  
  10.   
  11. is.reset();  
  12. int firstAgain = is.read();  
  13. int secondAgain = is.read();  
  14.   
  15. assertEquals(first, firstAgain);  
  16. assertEquals(second, secondAgain);  

 

Writer或者OutputStream中的flush(): 刷新该流的缓冲,用于确保数据的输出。

 

close(): 关闭流并释放与之关联的所有系统资源。

 

********************************************分割线*******************************************

了解了上面的概念之后,下面就开始讨论乱码的问题。

下面一段也是摘自网络,网址忘记了。

 

假设新建一个字符串如下:

String strMsg = new String("消息".getBytes("GBK"),"UTF-8");

这种方式只是在JVM内部转换,那么一旦涉及到流比如数据库、文件等就要使用java IO进行转换。

也就是说JVM内部编码unicode和外部os编码的转换。

如果直接使用***Writer.write(strMsg)等等,在接收方会有一定概率出现乱码,至于乱码的产生和很多因素有关,比如页面编码,不同JVM或OS编码不同等。


使用下面方式就没有问题了

 

字符流方式发送
PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream),"UTF-8")),false);

字节流方式发送
PrintStream ps = new PrintStream(socket.getOutputStream(),false,"UTF-8");
false表示手动pw.flush();

分享到:
评论

相关推荐

    egg-socket-io的demo案例

    主要实现egg利用egg-socket.io 和前端建立长链接 。里面2个文件egg、和html,一个是egg的 你更新下依赖,可以直接启动,还一个是html可以直接测试后端的推送。 演示地址看这里...

    swift-socket.io-client-swiftSocket.IO客户端

    在这个压缩包中,包含的是版本号为40d16de的socketio-socket.io-client-swift源代码。 首先,我们来深入理解Swift Socket.IO客户端的核心概念: 1. **事件驱动**:Socket.IO客户端基于事件模型,允许开发者订阅...

    ngx-socket-io:Angular的Socket.IO模块

    ngx-socket-io 模块 安装 npm install ngx-socket-io 如何使用 导入和配置SocketIoModule import { SocketIoModule , SocketIoConfig } from 'ngx-socket-io' ; const config : SocketIoConfig = { url : '...

    Vue-Socket.io, vuejs的socket.io 实现.zip

    Vue-Socket.io, vuejs的socket.io 实现 Vue-Socket.io Vuejs 2和Vuex的socket.io 实现安装npm install vue-socket.io --save用法配置从URL字符串自动连接import V

    perl-IO-Socket-SSL-1.94-7.el7.noarch.rpm

    官方离线安装包,亲测可用。使用rpm -ivh [rpm完整包名] 进行安装

    socket.io,socket.io-client下载

    Socket.IO和Socket.IO-Client是两个非常重要的库,主要用于实现实时双向通信,尤其是在Web开发领域。它们使得JavaScript客户端(浏览器)与Node.js服务器之间能够建立WebSocket风格的连接,提供了强大的实时通信解决...

    Java知识点总结大全(五) -- IO流.xmind

    Java知识点总结大全(五) -- io流,关注后面会分享面向对象,io,集合,多线程,网络,sql的总结

    Go-socket.io在golang中的一个实现一个实时应用程序框架

    go-socket.io是socket.io在golang中的一个实现,一个实时应用程序框架

    基于vue3+socket.io的聊天应用,比较完整,略好看.zip

    基于vue3+socket.io的聊天应用,比较完整,略好看 基于vue3+socket.io的聊天应用,比较完整,略好看 基于vue3+socket.io的聊天应用,比较完整,略好看 基于vue3+socket.io的聊天应用,比较完整,略好看 基于vue3...

    express-socket.io-session, socket.io 共享基于cookie的会话中间件.zip

    express-socket.io-session, socket.io 共享基于cookie的会话中间件 express-socket.io-sessionsocket.io 共享基于cookie的会话中间件。 使用英镑表示的> 4.0.0 和英镑> 1.0.0,不支持向后兼容。帮助我注意错误或者...

    socket -- io 小例子

    Socket.IO 是一个实时应用程序框架,它为Web开发者提供了一种简单的方式来实现实时、双向通信。这个框架在Node.js环境中运行,结合了WebSocket和其他多种浏览器兼容的通信协议,以克服WebSocket在某些环境下的局限性...

    commons-io-1.4.jar.zip_io流jar

    Java IO流体系结构分为四类:字节流(Byte Stream)、字符流(Character Stream)、对象流(Object Stream)和套接字流(Socket Stream)。字节流处理单个8位的字节,而字符流基于Unicode编码,处理16位的字符。对象...

    使用socket.io + Vue + uni-app搭建的完整分离版客服系统源码.zip

    使用socket.io + Vue + uni-app搭建的完整分离版客服系统,clone下来后安装必要依赖即可跑起来,功能众多,注释详细。 使用socket.io + Vue + uni-app搭建的完整分离版客服系统,clone下来后安装必要依赖即可跑...

    nuxt-socket-io:Nuxt Socket IO-Nuxt的socket.io客户端和服务器模块

    nuxt-socket-io 客户端和服务器模块特征多个IO插座的组态每个套接字名称空间的配置IO服务器自动注册套接字IO状态自动错误处理调试日志记录,通过将localStorage项目“ debug”设置为“ nuxt-socket-io”启用自动拆解...

    Angular-ngx-socket-io.zip

    Angular-ngx-socket-io.zip,角6NGX插槽IO的socket.io模块,Angularjs于2016年发布,是Angularjs的重写版。它专注于良好的移动开发、模块化和改进的依赖注入。angular的设计目的是全面解决开发人员的web应用程序工作流...

    socket.io源码

    这个源码包是 C++ 实现的 Socket.IO 客户端库,名为 "socket.io-clientpp",位于 "socket.io-clientpp-master" 压缩包中。下面将深入探讨相关知识点。 1. **Socket 基础** - **Socket**:Socket 是操作系统提供的...

    socket.io-cpp-client-sample:Socket.IO C++ 客户端示例

    socket.io-cpp-client-sample Socket.IO C++ 客户端示例。 该程序将本机客户端外壳上的命令结果提供给 Web 浏览器。 这个程序在有解释。 如何使用。 编译本机客户端。 $ git clone ...

    微信小程序socket.io客户端, 支持微信小程序、支付宝小程序socket.io-mp-client-master.zip

    这个名为"socket.io-mp-client-master.zip"的压缩包包含了专门为微信小程序和支付宝小程序设计的Socket.IO客户端库,名为"socket.io-mp-client"。 1. **WebSocket协议**:Socket.IO基于WebSocket协议,WebSocket是...

    适用于uni-app的socket.io封装,可用于uni-app、微信小程序.zip

    微信小程序的优势在于它方便快捷、轻量级、跨平台、丰富的推广方式、丰富的功能接口、数据分析与优化、结合微信支付、支持多场景应用、社交功能以及多端同步等。这些优点使得小程序能够满足用户的多种需求,提供更好...

    Java开发案例-springboot-12-集成socket.io服务端和客户端-源代码+文档.rar

    Java开发案例-springboot-12-集成socket.io服务端和客户端-源代码+文档.rar Java开发案例-springboot-12-集成socket.io服务端和客户端-源代码+文档.rar Java开发案例-springboot-12-集成socket.io服务端和客户端-源...

Global site tag (gtag.js) - Google Analytics