热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

java字符流字节流

java对文本文档进行操作(拷贝、显示)出现乱码一般来说,可以从两个方面入手。1、文本文件本身的编码格式。2、java代码中处理文本文件的编码格式。这里要注意的一点是,我们可以看出

java对文本文档进行操作(拷贝、显示)出现乱码一般来说,可以从两个方面入手。

1、文本文件本身的编码格式。

2、java代码中处理文本文件的编码格式。

这里要注意的一点是,我们可以看出copyFileByByte方法和copyFileByChar1方法都是没有办法设置目的文件的编码格式的,并且处理不好都可能出现乱码,但是需要明确一点的是,copyFileByByte方法拷贝的文件即便出现乱码也可以通过另存为其他格式来调整消除乱码,同样的操作在copyFileByChar1方法拷贝生成的源文件是不能消除乱码的。
技术分享

假设我们以字节流格式来读取一份utf-8编码格式的txt文档:

package com.audi;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class ReadFile
{
File fileName
= new File("C:/Users/Mike/Desktop/为什么使用接口.txt");
public void readFileByByte()
{
InputStream inputStream
=null;
try
{
inputStream
= new FileInputStream(fileName);
byte[] temp = new byte[2048];
StringBuilder buf
= new StringBuilder(); //非线程安全,不过这里是单线程,无所谓线程安全与否
int length = 0;
while (-1!=(length=inputStream.read(temp)))
{
// 注意下面的代码使用utf-8作为编码格式
buf.append(new String(temp,0,length,"utf-8"));
}
System.out.println(buf.toString());

}
catch (FileNotFoundException e)
{
e.printStackTrace();
System.out.println(
"文件C:/Users/Mike/Desktop/为什么使用接口.txt不存在");
}
catch (IOException e) {
e.printStackTrace();
}
finally {
try
{
if (inputStream!=null)
{
inputStream.close();
}
}
catch (Exception e2)
{
e2.printStackTrace();
}

}

}

public void readFileByChar()
{

}
}

文本文件本来的内容为:

技术分享

测试代码如下:

package com.audi;
public class Test
{
public static void main(String[] args)
{
ReadFile readFile
= new ReadFile();
readFile.readFileByByte();
}
}

运行程序读取文本文件得到的控制台输出:

技术分享

可以看出中文没有乱码,一切正常,如果我们在在上面的代码中不设置解码格式,运行程序,依然正常,这是为什么?

这是因为我的java文件的默认编码格式就是utf-8,所以java代码在编译的时候默认就取了这个格式作为解码格式。

如果换成GBK,那么一样会出现乱码:

技术分享

技术分享

那么如果我们要使用字节流拷贝一份文本文件呢?

java代码如下:

public void copyFileByByte()
{
InputStream inputStream
= null;
OutputStream outputStream
= null;
File destName
= new File("copyFileByByte.txt");
try
{
inputStream
= new FileInputStream(fileName);
outputStream
= new FileOutputStream(destName);
int length =0;
byte[] temp = new byte[2048];
while (-1!=(length=inputStream.read(temp)))
{
outputStream.write(temp,
0, length);
}
outputStream.flush();
}
catch (Exception e)
{
e.printStackTrace();
}
finally {
try
{
if (inputStream!=null)
{
inputStream.close();
}
if (outputStream!=null)
{
outputStream.close();
}
}
catch (Exception e2)
{
e2.printStackTrace();
}
}
}

测试代码如下:

package com.audi;
public class Test
{
public static void main(String[] args)
{
ReadFile readFile
= new ReadFile();
// readFile.readFileByByte();
readFile.copyFileByByte();
}
}

我的实际测试结果是,拷贝后的文件的编码格式是由源文件格式决定的,它会和源文件的格式保持一致。一般不会出现乱码。

 

下面是使用字符流来操作文本文件。

public void readFileByChar()
{
Reader reader
= null;
try
{
reader
= new BufferedReader(new FileReader(fileName));
int length =0;
char[] temp = new char[2048];
StringBuilder buf
= new StringBuilder();
while (-1!=(length=reader.read(temp)))
{
buf.append(
new String(temp, 0, length));
}
System.out.println(buf.toString());
}
catch (FileNotFoundException e)
{
e.printStackTrace();
System.out.println(
"文件C:/Users/Mike/Desktop/为什么使用接口.txt不存在");
}
catch (IOException e) {
e.printStackTrace();
}
}

上面的代码和字节流读取文件不同的是:

1、缓冲数组改成了char[]类型

2、new string构造函数中不能再设定格式,这将会导致它直接使用测试的java文件格式来解码读取的字符流。如下图所示,因为我的txt文档也是utf-8格式的,所以不会出现乱码错误。

技术分享

测试代码:

package com.audi;
public class Test
{
public static void main(String[] args)
{
ReadFile readFile
= new ReadFile();
// readFile.readFileByByte();
// readFile.copyFileByByte();
readFile.readFileByChar();
}
}

实际运行效果;

技术分享

如果把测试java文件的编码格式改为gbk,那么就会出现乱码

技术分享

下面以字符流方式拷贝文件,同样无法手动设置文件的编码格式:

public void copyFileByChar1()
{
FileReader fReader
= null;
FileWriter fWriter
= null;
File destName
= new File("copyFileByChar1.txt");
try
{
fReader
= new FileReader(fileName);
fWriter
= new FileWriter(destName);
int length =0;
char[] temp = new char[2048];
while (-1!=(length=fReader.read(temp)))
{
fWriter.write(temp,
0,length);
}
}
catch (FileNotFoundException e)
{
e.printStackTrace();
System.out.println(
"文件C:/Users/Mike/Desktop/为什么使用接口.txt不存在");
}
catch (IOException e) {
e.printStackTrace();
}
finally
{
try
{
if (fReader!=null)
{
fReader.close();
}
if (fWriter!=null)
{
fWriter.close();
}
System.out.println(
"copy succeed");
}
catch (Exception e2)
{
e2.printStackTrace();
}
}
}

测试代码,拷贝后文件的格式依然会和测试代码的java文件的编码格式保持一致。

package com.audi;
public class Test
{
public static void main(String[] args)
{
ReadFile readFile
= new ReadFile();
// readFile.readFileByByte();
// readFile.copyFileByByte();
// readFile.readFileByChar();
readFile.copyFileByChar1();
}
}

这里要注意的一点是,我们可以看出copyFileByByte方法和copyFileByChar1方法都是没有办法设置目的文件的编码格式的,并且处理不好都可能出现乱码,但是需要明确一点的是,copyFileByByte方法拷贝的文件即便出现乱码也可以通过另存为其他格式来调整消除乱码,同样的操作在copyFileByChar1方法拷贝生成的源文件是不能消除乱码的。

下面介绍另外一种方法来拷贝文件,使用的是InputStreamReader和OutputStreamWriter:

public void copyFileByChar2()
{
InputStreamReader inputStreamReader
=null;
OutputStreamWriter outputStreamWriter
= null;
File destName
= new File("copyFileByChar2.txt");

try
{
/*其实只有InputStreamReader和OutputStreamWriter才可以设置编码格式
*
*
*/
inputStreamReader
= new InputStreamReader(new java.io.FileInputStream(fileName),"utf-8");
outputStreamWriter
= new OutputStreamWriter(new java.io.FileOutputStream(destName),"utf-8");
int length =0;
char[] temp = new char[2048];
while (-1!=(length=inputStreamReader.read(temp)))
{
outputStreamWriter.write(temp,
0,length);
}
}
catch (UnsupportedEncodingException e1)
{
e1.printStackTrace();
}
catch (FileNotFoundException e1)
{
e1.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
outputStreamWriter.flush();
if (inputStreamReader!=null)
{
inputStreamReader.close();
}
if (outputStreamWriter!=null)
{
outputStreamWriter.close();
}
}
catch (Exception e2)
{
e2.printStackTrace();
}
System.out.println(
"拷贝结束了");
}
}

这个时候拷贝文件的格式完全可控,再也不会依赖测试文件的格式了。

此时,设置源文件UTF-8格式,测试java文件GBK格式:

技术分享

运行测试代码:

package com.audi;
public class Test
{
public static void main(String[] args)
{
ReadFile readFile
= new ReadFile();
// readFile.readFileByByte();
readFile.copyFileByByte();
// readFile.readFileByChar();
readFile.copyFileByChar1();
readFile.copyFileByChar2();
}
}

拷贝后的文件,没有出现乱码:

技术分享

最后,其实我们上面一直在强调都是针对文本文件的操作,那如果是非文本文件呢?

非文本文件?什么?

严格来说,文件只有两种类型:文本文件(也叫ASCII文件)和二进制文件。

ASCII码:  00110101 00110110 00110111 00111000
            ↓      ↓    ↓   ↓
十进制码:           5     6    7    8 共占用4个字节。

二进制文件是按二进制的编码方式来存放文件的。 例如, 数5678(五千六百七十八,十进制)的存储形式为:

00010110 00101110(二进制)只占二个字节。

非文本文件我们只能通过字节流来操作,因为字节流虽然也不能设置编解码格式,但是它是一个一个字节读取的,源文件是什么样,拷贝出的文件也是什么样,特定的解码器再去解码就可以了。

字符流就不一样了,它会根据设定的编解码格式的不同,一次读取两个或者三个字节来进行编解码,这样很可能会损坏源文件的编码方式,导致拷贝的文件出错。


推荐阅读
  • Python 伦理黑客技术:深入探讨后门攻击(第三部分)
    在《Python 伦理黑客技术:深入探讨后门攻击(第三部分)》中,作者详细分析了后门攻击中的Socket问题。由于TCP协议基于流,难以确定消息批次的结束点,这给后门攻击的实现带来了挑战。为了解决这一问题,文章提出了一系列有效的技术方案,包括使用特定的分隔符和长度前缀,以确保数据包的准确传输和解析。这些方法不仅提高了攻击的隐蔽性和可靠性,还为安全研究人员提供了宝贵的参考。 ... [详细]
  • 本文深入探讨了Java多线程环境下的同步机制及其应用,重点介绍了`synchronized`关键字的使用方法和原理。`synchronized`关键字主要用于确保多个线程在访问共享资源时的互斥性和原子性。通过具体示例,如在一个类中使用`synchronized`修饰方法,展示了如何实现线程安全的代码块。此外,文章还讨论了`ReentrantLock`等其他同步工具的优缺点,并提供了实际应用场景中的最佳实践。 ... [详细]
  • 在 Mac 上查看隐藏文件和文件夹的详细指南。通过终端命令,您可以轻松地显示或隐藏这些文件。具体步骤如下:输入 `defaults write com.apple.finder AppleShowAllFiles -bool true` 以显示所有隐藏文件,或使用 `defaults write com.apple.finder AppleShowAllFiles -bool false` 以重新隐藏它们。此方法适用于各种版本的 macOS,帮助用户更好地管理和访问系统文件。 ... [详细]
  • 二分查找算法详解与应用分析:本文深入探讨了二分查找算法的实现细节及其在实际问题中的应用。通过定义 `binary_search` 函数,详细介绍了算法的逻辑流程,包括初始化上下界、循环条件以及中间值的计算方法。此外,还讨论了该算法的时间复杂度和空间复杂度,并提供了多个应用场景示例,帮助读者更好地理解和掌握这一高效查找技术。 ... [详细]
  • 在 Android 开发中,`android:exported` 属性用于控制组件(如 Activity、Service、BroadcastReceiver 和 ContentProvider)是否可以被其他应用组件访问或与其交互。若将此属性设为 `true`,则允许外部应用调用或与之交互;反之,若设为 `false`,则仅限于同一应用内的组件进行访问。这一属性对于确保应用的安全性和隐私保护至关重要。 ... [详细]
  • 在最近的项目中,我们广泛使用了Qt框架的网络库,过程中遇到了一些挑战和问题。本文旨在记录这些经验和解决方案,以便日后参考。鉴于我们的客户端GUI完全基于Qt开发,我们期望利用其强大的网络功能进行Fiddler网络数据包的捕获与分析,以提升开发效率和应用性能。 ... [详细]
  • 在 iOS 开发中,经常会遇到 `@(YES)`、`@[firstViewController]` 以及 `@{@a:@b}` 这样的语法糖。这些简化的写法分别用于初始化布尔值、数组和字典对象,能够显著提高代码的可读性和编写效率。例如,`@(YES)` 可以快速创建一个布尔值对象,`@[firstViewController]` 则用于创建包含单个元素的数组,而 `@{@a:@b}` 则用于创建键值对字典。理解这些语法糖的使用方法,有助于开发者更加高效地进行编码。 ... [详细]
  • 题目要求解决一个有趣的编程挑战,即计算由四个自然数 \( p, q, r, s \) 组成的分数序列的和。具体来说,需要编写一个 C# 程序来处理这些自然数,并通过特定的数学运算得出最终结果。该任务不仅考验编程技能,还涉及对数学公式的理解和应用。 ... [详细]
  • 在 Axublog 1.1.0 版本的 `c_login.php` 文件中发现了一个严重的 SQL 注入漏洞。该漏洞允许攻击者通过操纵登录请求中的参数,注入恶意 SQL 代码,从而可能获取敏感信息或对数据库进行未授权操作。建议用户尽快更新到最新版本并采取相应的安全措施以防止潜在的风险。 ... [详细]
  • Nginx 反向代理配置与应用指南
    本文详细介绍了 Nginx 反向代理的配置与应用方法。首先,用户可以从官方下载页面(http://nginx.org/en/download.html)获取最新稳定版 Nginx,推荐使用 1.14.2 版本。下载并解压后,通过双击 `nginx.exe` 文件启动 Nginx 服务。文章进一步探讨了反向代理的基本原理及其在实际应用场景中的配置技巧,包括负载均衡、缓存管理和安全设置等,为用户提供了一套全面的实践指南。 ... [详细]
  • POJ 2482 星空中的星星:利用线段树与扫描线算法解决
    在《POJ 2482 星空中的星星》问题中,通过运用线段树和扫描线算法,可以高效地解决星星在窗口内的计数问题。该方法不仅能够快速处理大规模数据,还能确保时间复杂度的最优性,适用于各种复杂的星空模拟场景。 ... [详细]
  • 本指南详细介绍了如何在CentOS 6.6 64位系统上以root用户身份部署Tomcat 8服务器。系统环境为CentOS 6.6 64位,采用源码安装方式。所需软件为apache-tomcat-8.0.23.tar.gz,建议将软件下载至/root/opt目录。具体下载地址请参见官方资源。本指南涵盖了从环境准备到服务启动的完整步骤,适用于需要在该系统环境下搭建高性能Web应用服务器的技术人员。 ... [详细]
  • 该问题可能由守护进程配置不当引起,例如未识别的JVM选项或内存分配不足。建议检查并调整JVM参数,确保为对象堆预留足够的内存空间(至少1572864KB)。此外,还可以优化应用程序的内存使用,减少不必要的内存消耗。 ... [详细]
  • 在数字图像处理中,Photoshop 的直方图是一个重要的工具,它能够精确地反映图像中不同亮度级别的分布情况。通过分析直方图,用户可以深入了解图像的曝光、对比度和色调范围,从而进行更精细的调整。直方图不仅模拟了物体表面反射光线的原理,还能帮助摄影师和设计师更好地掌握图像的明暗细节,优化视觉效果。 ... [详细]
  • 这是一道涉及数学计算的问题。假设步行速度为 \(a\),车速为 \(b\),总距离为 \(c\)。Teddy 的步行时间为 \(T_1\),WhereIsHeroFrom 的步行时间为 \(T_2\),总时间为 \(T\)。通过分析不同时间段内的速度变化,可以得出最优的车辆使用策略,以最小化总的旅行时间。具体来说,需要计算在不同情况下步行和乘车的时间分配,以确保整体效率最大化。 ... [详细]
author-avatar
Yomon-00
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有