Idiot-maker

   :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  55 随笔 :: 1 文章 :: 17 评论 :: 0 引用

公告

2012年3月22日 #

http://sobaid.blogbus.com/logs/59873645.html

一、什么是流:

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

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

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

 

二、字节流和字符流

      如果数据流中最小的数据单元是字节,那么称这种流为字节流;如果数据流中最小的数据单元是字符,那么称这种流为字符流。在Java的IO系统中,java.io.InputStream和java.io.OutputStream分别表示字节输入流字节输出流,java.io.Reader和java.io.Writer分别表示字符输入流字符输出流

I/O流的层次

1.字节流:

从InputStream和OutputStream派生出来的一系列类。这类流以字节(byte)为基本处理单位。

◇ InputStream、OutputStream

  ◇ FileInputStream、FileOutputStream

  ◇ PipedInputStream、PipedOutputStream

  ◇ ByteArrayInputStream、ByteArrayOutputStream

  ◇ FilterInputStream、FilterOutputStream

  ◇ DataInputStream、DataOutputStream

  ◇ BufferedInputStream、BufferedOutputStream

 2.字符流:

从Reader和Writer派生出的一系列类,这类流以16位的Unicode码表示的字符为基本处理单位。

◇ Reader、Writer

  ◇ InputStreamReader、OutputStreamWriter

    ◇ PipedReader、PipedWriter

  ◇ FileReader、FileWriter

  ◇ CharArrayReader、CharArrayWriter

  ◇ FilterReader、FilterWriter

  ◇ BufferedReader、BufferedWriter

  ◇ StringReader、StringWriter

 3.对象流

  ◇ ObjectInputStream、ObjectOutputStream

 

4.其它

  ◇ 文件处理:

  File、RandomAccessFile;

  ◇ 接口

  DataInput、DataOutput、ObjectInput、ObjectOutput
三、字节流

    1. 处理概述:  

对于字节流处理的类都继承自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)   

用于将字节写入输出流。

2. 字节流:

字节流的处理类有很多,他们都继承自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。

 四、字符流:

1.  字符流处理概述

所有的字符流操作类都继承自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);   

write(String str, int off, int len);  

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

 

   2. 字符流处理

 

输入流:

       跟数据源直接接触的类:

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. // The read limit has no effect.   
  5. is.mark(0);     
  6. int first = is.read();   
  7. int second = is.read();     
  8. is.reset();   
  9. int firstAgain = is.read();   
  10. int secondAgain = is.read();     
  11. assertEquals(first, firstAgain);   
  12. assertEquals(second, secondAgain);  

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

 

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

posted @ 2012-03-22 15:02 NickyYe 阅读(22) 评论(0) 编辑

InputStream类的方法:

int read() 从输入流中读取一个字节的内容,并且把这个内容以整数的形式返回。如果碰到流的结束处,那么返回的值就是“-1”;如果流没有结果,但临时没有数据可读,那read方法就将阻塞运行程序的执行过程,至到流中有新的数据可读。

 

"到达流末尾,read方法返回的是-1",即意味着流中没有数据了,这一般用于判断读取文件内容是结束,即文件的结束符标志位;

如果是在socket上读,根据我的经验,这个方法是不灵光的,会有3种情况:
1. 网络断掉的话,抛出IOException;
2.例如流中只有八个字节了(对端仅写入了这么多)而你要read第9个,则抛出EOFException,
第三种情况要看你设置的socket的timeOut的值了,网络中读取时,不能根据read返回是否为-1决定是否还有数据,read时会block到超时再返回。

所以类似于下面的代码:

                InputStream in = clientSocket.getInputStream();

                int n = 0;
                byte[] buf = new byte[1024];
                String recvSocketMsg = "";
                while ((n = in.read(buf)) > 0) {
                    recvSocketMsg += new String(buf, 0, n);
                }

想要server不永远处在while里面,OutputStream必须close,或者给个结束符,flush是没用的。

但是out.close会把socket整个关掉,也就是说InputStream也用不了了。

Server端可以这样

                InputStream is = clientSocket.getInputStream();

int count = 0;
while (count == 0) {
count = is.available();
}
byte[] b = new byte[count];
is.read(b);

String recvSocketMsg = new String(b, 0, count);

但是,以上方法可能读不到末尾,目前原因未知,可能是网络问题导致is.available()返回不正确,在已知报文格式的情况下,可以设置读到某个字符终止

           while((readInt=input.read()) != -1) {  
request += (char)readInt;
if(request.indexOf("</endXML>") != -1){
break;
}

以上是一个字节读入,遇到中文会乱码,可以改用以下方法

               int n = 0;
byte[] buf = new byte[3072];
while ((n = is.read(buf)) > 0) {
recvSocketMsg += new String(buf, 0, n);
if (recvSocketMsg.indexOf("</CFX>") != -1) {
break;
}
}

http://blog.sina.com.cn/s/blog_565ea189010001fp.html

http://www.iteye.com/topic/165013

http://my.oschina.net/hunterli/blog/14938

http://ansonlai.iteye.com/blog/556287

posted @ 2012-03-22 14:42 NickyYe 阅读(46) 评论(0) 编辑

2012年1月16日 #

http://space.itpub.net/471666/viewspace-207344

ORA-02064 distributed operation not supported


Cause:One of the following unsupported operations was attempted:

  • Array execute of a remote update with a subquery that references a database link, or
  • An update of a long column with bind variable and an update of a second column with a subquery that both references a database link and a bind variable, or
  • A commit is issued in a coordinated session from an RPC with OUT parameters.

Action:Simplify the remote update statement.

问题: 数据库A ,B 通过DBlink互相访问, 数据库A 调用数据库B的存储过程pro_b , pro_b 过程中有out 输出参数,并且里面有dml语句,之后commit ,或rollback. 这时数据库A 通过DBlink 的调用pro_b@B就会产生这个错误.

解决办法:

1. 去掉pro_b中的commit, rollback ,统一有数据库B来控制事务.(当然也可以去掉out参数,这样也破坏是事务的完整性)

2.用自制事务来控制pro_b , 在pro_b中添加.PRAGMA AUTONOMOUS_TRANSACTION; 优点:不用去修改调用的所有方法.当然这样也不能控制事务的完整.

http://jordan1226.itpub.net/post/989/459566

今天,开发人员在调用远端数据库的过程truncate表的时候,oracle提示 ORA-02064,

查询了一下oracle文档,对于这个错误的描述如下:

ORA-02064 distributed operation not supported

Cause:One of the following unsupported operations was attempted:

Array execute of a remote update with a subquery that references a database link, or
An update of a long column with bind variable and an update of a second column with a subquery that both references a database link and a bind variable, or
A commit is issued in a coordinated session from an RPC with OUT parameters.
Action:Simplify the remote update statement.

我们业务的实现: 过DBLINK调用远程数据库的存储过程,进行TRUNCATE TABLE,并返回成功与否的标志。

根据oracle文档的描述,问题应该出在返回标志的问题上,我试了一下,如果,不用返回参数的时候,过程可以成功执行,如果加上返回参数,则提示ORA-02064

应该是oracle认为远程调用过程,执行和返回标志是一个完整的事务,如果要返回到远端,那么就破坏了事务的完整性,所以提示ORA-02064

这个问题的解决办法有两个:1.不要返回标志,根据过程是否成功执行,在本地做判断,2.在远端的过程中加入 PRAGMA AUTONOMOUS_TRANSACTION; 这句话,制定义事务.

修改后的过程,如下

CREATE OR REPLACE PROCEDURE P_EXECUTE_DDL(AN_O_RET_CODE OUT NUMBER,
AC_O_RET_MSG OUT VARCHAR2,
AC_I_DDL IN VARCHAR2) IS
/******************************************************************
项目名称:E_SIM6.0
所属用户:EA_CGYW
概要说明:
中文名称:提供远程数据库(进行DDL操作)调用
语法信息:
用途简述:提供远程数据库(进行DDL操作)调用
输入参数:
输出参数:
调用举例:
VARIABLE AN_O_RET_CODE NUMBER;
VARIABLE AC_O_RET_MSG VARCHAR2;
EXEC P_EXECUTE_DDL(:AN_O_RET_CODE,:AC_O_RET_MSG,'TRUNCATE TABLE TABLE_NAME');
功能修订:
简要说明:

修订记录:
修订日期 修订人 修改内容简要说明
---------- ---------- ------------------------------

******************************************************************/
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
AC_O_RET_MSG := '操作成功';
AN_O_RET_CODE := 0;

EXECUTE IMMEDIATE AC_I_DDL;

EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
AN_O_RET_CODE := -1;
AC_O_RET_MSG := '错误代码:' || SQLCODE || CHR(13) || '错误信息:' || SQLERRM;
END P_EXECUTE_DDL;

这样就可以远程调用了,清空远程的表了.

在这里要感谢 蜗牛,songsong 对本人的支持,非常感谢,让我又学到了一招:)!!!!!!!!

posted @ 2012-01-16 10:54 NickyYe 阅读(41) 评论(0) 编辑

http://www.4ucode.com/Study/Topic/726884

废话少说,直接切入主题
步骤1:建立一个远程数据库的连接服务名
D:\oracle\ora92\network\admin\tnsnames.ora 添加如下代码:
SDEC =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.254)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = DEC)
    )
  )

步骤2:本地数据库建立一个db link
  CREATE PUBLIC DATABASE LINK doko CONNECT TO gz IDENTIFIED BY GZ USING 'SDEC';

ps:这里的SDEC 就是上面配置的服务名

步骤3:编写远程数据库写个测试的存储过程
create or replace procedure test(a in integer,b out integer) is
begin
  b:=a+1000;
end test;

步骤4:编写本地数据库的存储过程
create or replace procedure test2 is
p integer;
begin
  test@doko(1,p);
  dbms_output.put_line('p='||p); 
end test2;

步骤5:本地测试存储过程
SQL> set serveroutput on
SQL> exec test2;
 
p=1001
 
PL/SQL procedure successfully completed
 
SQL> 


完毕!
posted @ 2012-01-16 10:53 NickyYe 阅读(10) 评论(0) 编辑

2011年12月22日 #

http://trailblizer.blog.163.com/blog/static/5963036420102313745674/

ODI知识模块

 

·KM是通用的,它们不引用具体的物理对象。

·KM可用来对影响进行分析

·KM不能像过程一样被执行,他们需要从接口、数据存储和模型中得到元数据

IKM SQL Incremental Update

在sql兼容的目标表在增量更新模式下整合数据,这个知识模型创建临时中间区来存储数据流。不适合于大数据量。使用这个知识模型的时候中转区要与目标数据服务器在同一个地方。

IKM SQL to SQL Append

使用这个模型的时候,中转区与目标区必须不同在一个服务器上。

IKM Oracle Incremental Update

在oracle目标表中按照增量模式整合数据。这个知识模型创建一个临时区表来存储数据流。它与目标表中的内容对比,来判断哪些记录需要插入、哪些需要更新。这个知识模型适合大量数据处理。使用这个知识模型的时候中转区要与目标数据服务器在同一个地方。

Reverse-engineering Knowledge Modules (RKM)

RKM最主要的功能为对一个模型进行反向操作。RKM负责连接应用系统并把结果传送到ODI资料库。这些元数据被暂时写入SNP_REV_xx表,然后RKM调用ODI的API从这些表中读取并写到ODI的工作资料库中。典型RKM的工作步骤:

1.使用OdiReverseResetTable命令对上次执行中在SNP_REV_xx表中的数据进行清除

2.从SNP_REV_SUB_MODEL, SNP_REV_TABLE, SNP_REV_COL,SNP_REV_KEY, SNP_REV_KEY_COL, SNP_REV_JOIN, SNP_REV_JOIN_COL, 

  SNP_REV_COND 表中.检索子模型、数据存储、列、外键、主键等。

3.通过OdiReverseSetMetaData命令更新工作资料库中的模型。

Check Knowledge Modules (CKM)

CKM负责使用定义好的一致约束来对一组数据集做检查。CKM用来保持数据质量的完整性,有下列两种使用方式:

1.检查已有数据的一致性。设置STATIC_CONTROL为"YES";①检查目前在数据存储中的数据,对转换过程不关心;②接口中的目标数据存储在加载流数据后被检查;

2.在数据写入目标表前对数据做检查。FLOW_CONTROL;记录读取目标表的约束,检查I$表把违反约束的记录删掉。

CKM将错误信息存放在E$开头的表中。典型步骤:

1.在中转区创建以E$开头的错误表;

2.把检查出的错误记录放到E$表中;

Loading Knowledge Modules (LKM)

ODI知识模块  - trailblizer - CRAZY BOY

LKM负责从远端服务器装载数据到中转区。接口中使用,把加载的数据放到C$表中。步骤:

1.创建以C$开头的表,用来存放从源服务器加载的记录;

2.LKM保持一组在源端经过适当转换后的记录;

3.LKM把记录加载到C$表中。

如果数据存储和中转区在相同的数据服务器上时,不需要LKM。

Integration Knowledge Modules (IKM)

ODI知识模块  - trailblizer - CRAZY BOY

IKM负责把最终数据写入目标表中,每个接口只使用一个IKM。做这一步的时候假定源数据已经通过LKM被加载到中转区的临时表(C$)中了。IKM把数据装载到以I$开头的临时表。

当中转区与目标服务器在一起时:

1.从C$表中检索数据;

2.如果需要flow check,IKM调用CKM来隔离错误记录,清理I$表;

3.从I$表把记录写到目标表;

4.把I$表中记录删除

这种KM只工作在目标服务器上,对大数据量的处理效率高。

Journalizing Knowledge Modules (JKM)

ODI知识模块  - trailblizer - CRAZY BOY

posted @ 2011-12-22 22:11 NickyYe 阅读(32) 评论(0) 编辑

仅列出标题  下一页