咱们在 Java 中常常会碰到如何把 InputStream 转换成 String 的情形,好比从文件或网络获得一个 InputStream,须要转换成字符串输出或赋给别的变量。java
未真正关注这个问题以前我经常使用的办法就是按字节一次次读到缓冲区,或是创建 BufferedReader 逐行读取。其实大可没必要费此周折,咱们能够用 Apache commons IOUtils,或者是 JDK 1.5 后的 Scanner,还可用 Google Guava 库的 CharStreams。到了 JDK7,若要从文件中直接获得字符串还能用 java.nio.file.Files#readAllLines 和 java.nio.file.Files#readAllBytes 方法。android
下面看各个例子,为可以实际用运,例子写在 main 方法里,并从文件得到一个 InputStream,代码中把可能要捕获的异常抛出来。再就是注意处理输入输出流时有涉及到字符集,字符集乱了就乱码了,默认字符集是 System.getProperty("file.encoding"),一般咱们都用 UTF-8,异常 UnsupportedEncodingException 继承自 IOException。apache
下面的 6 个方法中应该有一个你能看得上的吧,用 Groovy,Scala 的除外,若未找到一个遂意的,告诉我,你有好办法更应该告诉我。数组
1. 使用 JDK 5 的 Scanner 网络
package cc.unmi.test;
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.util.Scanner; /** * * @author Unmi * @Creation date: 2013-02-01 */ public class Test { /** * @param args * @throws FileNotFoundException */ public static void main(String[] args) throws FileNotFoundException { InputStream inputStream = new FileInputStream("d:/sample.txt"); Scanner scanner = new Scanner(inputStream, "UTF-8"); String text = scanner.useDelimiter("\\A").next(); System.out.println(text); scanner.close(); } }
2. JDK1.4 及以前的 BufferedReader 法app
package cc.unmi.test;
import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; /** * * @author Unmi * @Creation date: 2013-02-01 */ public class Test { /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { InputStream inputStream = new FileInputStream("d:/sample.txt"); StringBuilder stringBuilder = new StringBuilder(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); boolean firstLine = true; String line = null; ; while((line = bufferedReader.readLine()) != null){ if(!firstLine){ stringBuilder.append(System.getProperty("line.separator")); }else{ firstLine = false; } stringBuilder.append(line); } System.out.println(stringBuilder.toString()); } }
中间那些判断是否是第一行来决定是否加换行符是些杂音。测试
3. JDK1.4 及以前的 readBytes 法ui
package cc.unmi.test;
import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; /** * * @author Unmi * @Creation date: 2013-02-01 */ public class Test { /** * @throws IOException */ public static void main(String[] args) throws IOException { InputStream inputStream = new FileInputStream("d:/sample.txt"); byte[] buffer = new byte[2048]; int readBytes = 0; StringBuilder stringBuilder = new StringBuilder(); while((readBytes = inputStream.read(buffer)) > 0){ stringBuilder.append(new String(buffer, 0, readBytes)); } System.out.println(stringBuilder.toString()); } }
缓冲区的大小本身根据实际来调,比 BufferedReader 还简洁些,不需管换行符的事情。google
4. Apache commons IOUtils.toString 法编码
package cc.unmi.test;
import java.io.*; import org.apache.commons.io.IOUtils; /** * * @author Unmi * @Creation date: 2013-02-01 */ public class Test { /** * @throws IOException */ public static void main(String[] args) throws IOException { InputStream inputStream = new FileInputStream("d:/sample.txt"); String text = IOUtils.toString(inputStream); System.out.println(text); } }
第三方库就是第三方库,人家充分考虑到了你的感觉,你对 JDK 库的抱怨,多简洁,一行搞定。IOUtils 还能把内容拷入其余的 Writer 中,如 IOUtils.copy(inputStream, new StringWriter())。
5. Google guava 的 CharStreams 方法
package cc.unmi.test;
import java.io.*; import com.google.common.io.CharStreams; /** * * @author Unmi * @Creation date: 2013-02-01 */ public class Test { /** * @throws IOException */ public static void main(String[] args) throws IOException { InputStream inputStream = new FileInputStream("d:/sample.txt"); String text = CharStreams.toString(new InputStreamReader(inputStream, "UTF-8")); System.out.println(text); } }
CharSteams 不是直接做用在 InputSteam 上的,还要靠 InputStreamReader 拱个桥。
6. JDK 7 的 NIO readAllBytes
package cc.unmi.test;
import java.io.IOException; import java.nio.file.*; /** * * @author Unmi * @Creation date: 2013-02-01 */ public class Test { /** * @throws IOException */ public static void main(String[] args) throws IOException { byte[] bytes = Files.readAllBytes(Paths.get("d:/sample.txt")); String text = new String(bytes); System.out.println(text); } }
这让咱们相信 JDK 一直还有人在管,虽然不可能象动态语言的方法那么快捷,上面的 readAllBytes 在处理大文件时确定会很被动的。而 Files.readAllLines 会把文件的内容读入一个 List<String> 对象中,往内存不断放东西就得掂量下内存会不会被爆。在 java.nio.file.* 还有不少新事物可供发掘。
从SDCard保存的txt文件读取中文到android系统中会出现乱码问题,如何解决这个乱码问题,网上有很多解答方法,譬如说利用String temp1 =EncodingUtils.getString(strLine.getBytes(),"GB2312"); 但并不是对全部的状况都适用,解决乱码问题首先要明白为何会乱码。究其缘由,是由于txt文件在win系统上保存时默认为ANSI格式,而android目前只支持UTF-8编码,所以将txt文件的中文读入android系统中会产生乱码。也有人说直接将txt另存为UTF-8编码格式来解决乱码问题,但这种方法指标不治本,不能要求用户手动去更改格式,客户第一嘛。所以仍是须要想办法在程序中进行处理。
如下作了一些编码格式的测试:
测试文本: 122.11196,29.90573,北仑固废厂 测试代码段:
reader=new BufferedReader(new FileReader(filename));
strLine=reader.readLine() ;
String temp1 = EncodingUtils.getString(strLine.getBytes(),"GB2312");
String temp2 = EncodingUtils.getString(strLine.getBytes("utf-8"),"utf-8");
String temp3 = EncodingUtils.getString(strLine.getBytes(),"utf-8");
将文件存成 Unicode 格式
将文件存成utf-8 格式
这种方式能获得非乱码的中文显示,但对于 utf-8 格式下取得的经纬度数字利用double lon = Double.parseDouble(lat); 报错 NumberFormatException,缘由多是
parseDouble(lat)方法不能处理存成utf-8格式的带标点小数。 将文件 存成 ANSI 格式
将代码改成:
reader = new BufferedReader(new InputStreamReader(new FileInputStream(filename),"GB2312"));
strLine=reader.readLine() ;
String temp1 = EncodingUtils.getString(strLine.getBytes(),"GB2312");
String temp2 = EncodingUtils.getString(strLine.getBytes("utf-8"),"utf-8");
String temp3 = EncodingUtils.getString(strLine.getBytes(),"utf-8");
即解决了中文乱码问题,又解决了Double.parseDouble(lat)报错问题。