`
tworthree
  • 浏览: 3800 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

Java IO中的数字处理

阅读更多

2. Numeric Data


输入流读入字节,输出流写出字节,而reader读入字符,writer写出字符。因此要理解JavaIO首先要深入理解Java如何处理字节、整数、字符和其他的基本数据类型,它们之间什么时候并且为什么发生转型,很多情况下这些转型都不明显。

1.2.1. Integer Data


Java中int是4个字节前端高位后端低位由二进制补码表示的整型数据类型,,int的范围-2,147,483,648 到 2,147,483,647。对于数字7、-8345和

3,000,000,000编译器都处理成int数据,但是编译器对3,000,000,000这样大的数据会产生数据溢出错误。


而long数据是8个字节的,其前端是较高位,后端是最低位,由二进制补码组成,它的范围自-9,223,372,036,854,775,808到9,223,372,036,854,775,807。这样的大数据前加L或l后缀,例如7L, -8345L和3000000000L都是64位的长整型数据。为了不造成混淆,大写L比小写l要常用。


另外两种数据类型short和byte在Java中也可能见到,short是2字节前端高位后端低位由二进制补码表示的短整型数据类型,其范围-32,768 到32,767,short在Java中可能用到,并且对C语言有兼容性。


但是byte在Java中很常见,尤其是在JavaIO中,一个byte数据即一个字节,由二进制补码表示的整数,其范围-128 到 127。注意像Java中的所有数据类型一样,byte是有符号的。最大的值是127,对于byte比这大的数不合法。像42和24000这样的数字,编译器会当做int数据,而不是short或者byte数据,即使像下面显式声明byte和short数据,Java内部也是作为int来处理:


byte b = 42;

short s = 24000;

 

这些int数据在编译时时编译器理解为常量,但编译器允许其转型为byte和short窄类型的数据,并且是高效的。但是像下面这样简单的赋值来却达不到转型的目的:


int i = 42;

byte b = i;

 
编译器理论上知道这样转型并不会丢失数据,但编译这样的代码会报错:


Error:    Incompatible type for declaration.
Explicit cast needed to convert int to short.
ByteTest.java  line 6

要改正这个错误,需要这样显式转型


int i = 42;

byte b = (byte) i;

 
即使是两个byte数据产生的新数据赋值给byte也需要显式转型:


byte b1 = 22;

byte b2 = 23;

byte b3 = b1 + b2;

 
所以直接操作byte非常不方便。但JavaIO的某些方法的确是基于byte的,这些方法返回值或参数是一个无符号的字节表示的整数(0-255),这个范围说明它并不满足Java的基本数据类型,这就意味着需要内部转型。


例如根据Java类库文档的描述:the read( ) method of java.io.InputStream returns "the next byte of data, or -1 if the end of the stream is reached."但怎样区分数据中的-1和标志流尾的-1呢?有疑惑了吧,仔细思考一下(参看原文档源代码)


事实上,read方法返回的并不是一个byte,而是一个int:


public abstract int read( ) throws IOException

 
很显然这里的int不是byte数据,可以看作一个无符号的字节表示的整数(0-255)。因此,流尾的-1很容易和合法数据区分开。(合法数据-1被转型到0-255之间?)


java.io.OutputStream 中的write方法有相同的问题,它无返回值并且以一个int数据为参数


public abstract void write(int b) throws IOException

 
同样,这个int意味着一个无符号字节表示的整数(0-255),这个方法并不能防止因为程序员的疏忽传了超过这个范围的int数据。那么就需要去掉超出这个范围的三个字节:

b = b & 0x000000FF;

 
这在Java语言规范中有描述。


因为write是抽象的,具体的实现在子类中都有实现,但是如果自定义子类,粗心的程序员可能忽略这点。


byte在IO中还体现在另一方面,某些读写方法使用byte数组,例如下面这两个方法:


public int read(byte[] data) throws IOException

public int read(byte[] data, int offset, int length) throws IOException

 



操作一个单独的8位的byte数据和一个32位的int数据没有多大差别,但是如果很成百上千的数据需要读写的话就有很大区别。事实上,一个byte数据在Java虚拟机中占有4个字节空间,但是byte数组只占实际需要的大小空间。虚拟机对byte数组执行特殊的操作,但对单独的byte数据并没有操作,它仅仅是转型为int。


尽管byte数组使用的是有符号的值(-127-128),但IO操作时它们都有对应的无符号byte值,这种对应使用的下面这种方法:


int unsignedByte = signedByte >= 0 ? signedByte : 256 + signedByte;

 
1.2.2. Conversions and Casts转变和转型


byte数据范围很小,它们在计算和方法调用时都宽转变为int数据,通常它们需要窄转型回来,深入理解这种变化时非常有用的。


通过抹掉数据高位来达到int数据向byte数据的转型,其值并不会发生改变。int数据127转型为byte数据其值还是127。当然,如果int值太大的话,转型时数据值可能前后不一,int数据128转型为byte是-128。原因在于转型执行的二进制算法,128是用十六进制表示的,为0x00000080,转型为byte时需要抹掉高位结果为0x80。128用二进制表示为10000000,如果无符号是128,但是Java会看做是带符号的,这个1是符号位,通过补码加1得到其绝对的值。因此Ox80代表-128,诸如类推129代表-127,130代表-126,直到255代表-1。


所以,int数据256转型为byte是0,然后循环轮回。这个算法很简单,如下所示:


int byteValue;
int temp = intValue % 256;
if ( intValue < 0) {
  byteValue =  temp < -128 ? 256 + temp : temp;
}
else {
  byteValue =  temp > 127 ? temp - 256 : temp;
}

 

 

分享到:
评论

相关推荐

    Java_IO.rar_IO流 java_java io流

    Java IO流是Java编程语言中处理输入输出的重要组成部分,它为数据传输提供了高效且灵活的方式。在Java中,IO流可以分为两类:字节流(处理单个字节)和字符流(处理Unicode字符)。此外,它们又可以分为四大类:输入...

    java数字图像水印处理

    Java数字图像水印处理是一种在图像中嵌入隐藏信息的技术,通常用于版权保护、认证或追踪图像来源。在这个基于Eclipse的项目中,开发者利用Java的强大学术和工业支持,构建了一个简单但功能完备的数字水印系统,涵盖...

    java io流-3.pdf

    - **1.2 数字数据处理**:Java提供了多种处理数字数据的方法,包括`int`、`float`等类型的读写操作。 - **1.3 字符数据处理**:通过字符流处理文本数据,支持Unicode等多种字符集。 - **1.4 Reader和Writer类**:...

    数字图像处理java版源代码

    学习这个项目,你可以了解到如何在Java环境下使用基本的数据结构(如二维数组)来表示图像,以及如何利用Java的多线程和IO流进行高效处理。同时,对于初学者来说,通过阅读源码,能够加深对数字图像处理理论的理解,...

    Java IO 2nd

    该书提供了对Java I/O类及其相关类的全面覆盖,以及对Java数字格式化设施和国际字符集支持的深入探讨。本书不仅是Java程序员的必备参考资料,也是理解Java I/O系统内部运作的重要资源。 ### Java I/O的核心概念 ...

    JAVA IO流小结

    JAVA IO流是指Java语言中用来实现输入/输出操作的机制。IO流是指任何有能力产出数据的数据源对象或者有能力接收数据的数据源对象。他屏蔽了实际的I/O设备处理数据的细节。 一、流的定义和分类 流是指任何有能力...

    java IO数据流的输入输出

    Java IO(Input/Output)是Java编程语言中用于处理数据输入和输出的重要组成部分。它提供了一种机制,使得程序能够与外部设备如键盘、显示器、硬盘等进行数据交互。Java IO 包含了一系列的类和接口,使得开发者可以...

    java io 2nd

    在这一版中,作者深入探讨了Java的输入输出机制,包括流式I/O、数据源、过滤流、压缩流以及JAR归档等内容。读者可以通过本书理解Java I/O体系结构,并学会如何在实际开发中应用这些知识。 ### Java I/O基础 Java I...

    Java IO操作和将字符串解析为数值数组

    在Java编程语言中,IO(Input/Output)操作是处理数据输入和输出的关键部分,而将字符串解析为数值数组则是日常编程中常见的任务。本文将深入探讨这两个主题,并结合提供的两个文件名`TestWriteD.java`和`TestSplitD...

    java_IO操作_(读写、追加、删除、移动、复制、修改

    Java中的IO操作是进行文件处理的核心技术之一,涵盖了读写、追加、删除、移动、复制、修改等基本功能。本文将围绕这些操作展开详细解释,重点解析如何使用Java进行文件的读取。 ### 一、Java IO读取文件内容 #### ...

    java 数字图象处理

    import java.io.*; import process.algorithms.Introduction; import process.param.ResultShow; import process.common.Common; import process.rw.*; public class Ch1Introduction extends JFrame implements ...

    url传值异常java.io.CharConversionException: isHexDigit

    然而,有时在处理URL参数时可能会遇到一些异常,比如"java.io.CharConversionException: isHexDigit"。这个异常通常表明在尝试将URL中的十六进制字符转换为对应的ASCII字符时遇到了问题。在描述的场景中,这个问题...

    java.io的基础应用

    Java.IO(Input/Output)是Java编程语言中用于处理输入和输出操作的重要部分。它提供了大量的类和接口,使得开发者能够高效地与外部系统交互,包括磁盘、网络、内存缓冲区等。IO流的概念是Java.IO的核心,它将数据...

    JavaIO 2nd Edition PDF

    该书共有726页,全面覆盖了Java 5.0 API中的所有I/O类及相关类,并对Java的数字格式化设施进行了深入讲解,同时涵盖了国际字符集的支持。本书不仅适合Java初学者了解基础的I/O概念,也适用于有经验的开发者深入掌握...

    java.io.CharConversionException: isHexDigit 出现错误的原因及其解决办法

    在你的问题中,错误提示是"java.io.CharConversionException: isHexDigit",这通常意味着在处理字符或字符串时,程序尝试将某个字符识别为十六进制数字,但该字符并不符合十六进制数字的规则。 `isHexDigit`是一个...

    图像数字水印的JAVA实现

    在Java中实现图像数字水印涉及到多个关键知识点,包括图像处理、数据编码与解码以及水印算法的选择。下面我们将深入探讨这些核心内容。 1. **图像处理**:在Java中,我们可以使用`java.awt.image`和`javax.imageio`...

    Java IO.pdf

    以上知识点覆盖了 Java I/O 的基础概念以及核心类库的使用方法,对于理解 Java 如何处理文件和网络中的数据流提供了全面的视角。通过这些知识点的学习,开发者能够更加熟练地使用 Java 进行各种 I/O 相关的操作。

    java-IO操作-(读写、追加、删除、移动、复制、修改).doc

    java IO 操作是 Java 语言中对文件、流、输入/输出操作的统称。下面是 java IO 操作的详细知识点: 一、 java IO 操作的分类 java IO 操作可以分为两大类:输入/输出流(Stream)和读者/写者(Reader/Writer)。 ...

Global site tag (gtag.js) - Google Analytics