2010年11月3日
#
知識點一:分類
IO中按照數據流的方向不同可以分為輸入流和輸出流(以程序的角度來考慮)
按照數據單位的不同可以分為字節流和字符流。
按照功能的不同可以分為節點流和處理流。
知識點二: 四大等級結構
java語言的i/o庫提供了四大等級結構:InputStream,OutputStream,Reader,Writer四個系列的類。InputStream和OutputStream處理8位字節流數據, Reader和Writer處理16位的字符流數據。InputStream和Reader處理輸入, OutputStream和Writer處理輸出。大家一定要到J2SE文檔中看看這四大等級結構的類繼承體系。
除了這四大系列類,i/o庫還提供了少數的輔助類,其中比較重要的是InputStreamReader和OutputStreamWriter。InputStreamReader把InputStream適配為Reader, OutputStreamWriter把OutputStream適配為Writer;這樣就架起了字節流處理類和字符流處理類間的橋梁。
您使用I/O庫時,只要按以上的規則,到相應的類體系中尋找您需要的類即可
下面我就會對I/O 進行不定期更新:
1 FileOutputStream 文件字節流
Public class FileInputStream extends InputStream
{
/* File Descriptor - handle to the open file */
private FileDescriptor fd;
public FileInputStream(FileDescriptor fdObj)
{
SecurityManager security = System.getSecurityManager();
if (fdObj == null) {
throw new NullPointerException();
}
if (security != null) {
security.checkRead(fdObj);
}
fd = fdObj;
}
//其他代碼
}
可見,FileInputStream繼承了InputStream,組合了FileDescriptor,采用的是對象Adapter模式。我們學習i/o庫時,主要應該掌握這四個對象Adapter模式的適配源: ByteArrayInputStream的適配源是Byte數組, FileInputStream的適配源是File對象, PipedInputStream的適配源是PipedOutputStream對象, StringBufferInputStream的適配源是String對象
線程間通信:一個線程向數據存儲空間添加數據(唐老鴨),另一個線程從數據存儲空間取出數據(米琪)。
程序有兩種以外需要考慮:
1、 假設唐老鴨線程剛向數據存儲空間添加了一輛車的名字。還沒有加入這輛車的顏色,CPU就切換到了米琪線程,唐老鴨線程將把這輛車的名字和上輛車的顏色聯系到了一起。
2 、唐老鴨了若干次的數據。米琪才開始取數據,或者是,米琪取完了一個數據后,還沒等到唐老鴨放入新的數據,又重復取出已取過的數據。
可能出現的問題:
1唐老鴨比米琪快時,米琪會漏掉一些數據沒有取到。
2、 米琪比唐老鴨快時,米琪取相同的數據。
多個線程共享同一資源的時候,必須進行同步,采用同步方法,解決第一個問題。
線程的等待和喚醒機制:
wait():告訴當前線程放棄監視器并進入睡眠狀態,直到其他線程進入同一監視器并調用notify為止。
notify():喚醒同一對象監視器中調用wait的第一個線程。
程序中采用線程的等待和喚醒機制,當發現米琪沒有取走內容時,唐老鴨應該等待,當米琪把內容取走之后,唐老鴨才可以放。這樣解決了第二個問題。
代碼如下:
package Killva.IOchaper4.o3;
class Animal{
private String name ="唐老鴨";
private String sex= "公";
private boolean flag=false;
public synchronized void set(String name, String sex){//生產者
//如果flag的值不是true則要等待
if(!flag){
//等待
try{
wait();
}catch(Exception e){}
}
//如果向下繼續執行了,則表示可以設置, flag =true
this.name=name;
this.sex=sex;
//修改設置的標志
flag = false;
//喚醒其他線程
notify();
}
//設置一個輸出的方法
public synchronized void get(){
//如果flag的值為true的時候,表示要等待
if(flag){
try{
wait();
}catch(Exception e){}
}
//如果向下執行了,就表示允許
System.out.println(this.name+"-->"+this.sex);
//改變標簽
flag =true;
notify();
}
}
class Pro implements Runnable{
Animal per =null;
public Pro(Animal p){
this.per=p;
}
public void run() {
int i =0;
while (true){
if(i==0){
per.set("米琪", "母");
i=1;
}else{
per.set("唐老鴨", "公");
i=0;
}
}
}
}
class Cus implements Runnable{
Animal per =null;
public Cus(Animal p){
this.per=p;
}
public void run() {
while(true){
per.get();
}
}
}
public class Demo01 {
//主方法
public static void main(String[] args){
Animal per =new Animal();
Pro p =new Pro(per);
Cus c =new Cus(per);
new Thread(p).start();
new Thread(c).start();
}
}
運行結果:
感謝閱讀 !!!歡迎交流!!! QQ:237333696
所謂socket通常也稱作"套接字",用于描述IP地址和端口,是一個通信鏈的句柄。應用程序通常通過"套接字"向網絡發出請求或者應答網絡請求。Socket和ServerSocket類庫位于java.net包中。ServerSocket用于服務器端,Socket是建立網絡連接時使用的。在連接成功時,應用程序兩端都會產生一個Socket實例,操作這個實例,完成所需的會話。對于一個網絡連接來說,套接字是平等的,并沒有差別,不因為在服務器端或在客戶端而產生不同級別。不管是Socket還是ServerSocket它們的工作都是通過SocketImpl類及其子類完成的。
下面是我忍為比較重要的API:
1、. Accept方法用于產生"阻塞",直到接受到一個連接,并且返回一個客戶端的Socket對象實例。"阻塞"是一個術語,它使程序運行暫時"停留"在這個地方,直到一個會話產生,然后程序繼續;通常"阻塞"是由循環產生的。
2、. getInputStream方法獲得網絡連接輸入,同時返回一個InputStream對象實例,。
3、. getOutputStream方法連接的另一端將得到輸入,同時返回一個OutputStream對象實例。
注意:其中getInputStream和getOutputStream方法均會產生一個IOException,它必須被捕獲,因為它們返回的流對象,通常都會被另一個流對象使用。
寫代碼時一般先寫server端.
//Server
package Killva.NetWorkchaper1.o3;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class TestTCPServer {
public static void main(String args[])throws IOException{
ServerSocket ss =new ServerSocket(9999);
while(true){
System.out.println("--------服務端已近啟動------------");
Socket s =ss.accept();
DataOutputStream dos =new DataOutputStream(s.getOutputStream());
System.out.println("客戶端["+s.getInetAddress().getHostAddress()+
" :"+s.getPort()+
"]已近鏈接!");
dos.writeUTF("服務器端寫入客戶端的數據:客戶端("+
s.getInetAddress().getHostAddress()+
" :"+s.getPort()+
"]已經鏈接上服務器端["+
s.getLocalAddress().getHostName()+
":"+s.getLocalPort()+
"]!");
dos.flush();
dos.close();
s.close();
}
}
}
Client端
package Killva.NetWorkchaper1.o3;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
public class TestTCPCLient {
public static void main(String[] args) throws IOException{
System.out.println("-------------client端-----------");
for(long i=0;i<10;i++){
Socket s =new Socket("192.168.1.*",9999);//IP是用你所在的局域網來測試
DataInputStream dis = new DataInputStream(s.getInputStream());
System.out.println(""+dis.readUTF());
dis.close();
s.close();
}
}
}
運行結果真確時服務器端和客戶端能連接
感謝閱讀!!!!
創建線程有兩種方法:繼承Thread類和實現Runnable接口。
方法一:繼承 Thread 類,覆蓋方法 run(),我們在創建的 Thread 類的子類中重寫 run() ,加入線程所要執行的代碼即可。
a.每個線程都是通過某個特定Thread對象所對應的方法run()l來完成其操作的,方法run()成為線程體。
b.如果想要啟動多線程,則肯定調用start()方法,start方法可以調用被子類覆寫過的run方法
c.不過這種這種實現方式會受到單繼承的局限
下面是一個例子:
public class MyThread extends Thread {
int count= 1, number;
public MyThread(int num) {
number = num;
System.out.println("創建線程 " + number);
}
public void run() {
while(true) {
System.out.println("線程 " + number + ":計數 " + count);
if(++count== 6) return;
}
}
public static void main(String args[]) {
for(int i = 0; i < 5; i++) new MyThread(i+1).start();
}
}
方法二:實現 Runnable 接口
Runnable 接口只有一個方法 run(),我們聲明自己的類實現 Runnable 接口并提供這一方法,將我們的線程代碼寫入其中,就完成了這一部分的任務。
但是 Runnable 接口并沒有任何對線程的支持,我們還必須創建 Thread 類的實例,這一點通過 Thread 類的構造函數public Thread(Runnable target);來實現。
該實現方式有以下好處:
① 適合多個相干同程序代碼的線程去處理同一資源的情況。
② 可以避免由于Java單繼承特性帶來的局限。
③ 有利于程序的健壯性,代碼能夠被多個線程共享。
下面是一個例子:
public class MyThread implements Runnable {
int count= 1, number;
public MyThread(int num) {
number = num;
System.out.println("創建線程 " + number);
}
public void run() {
while(true) {
System.out.println("線程 " + number + ":計數 " + count);
if(++count== 6) return;
}
}
public static void main(String args[]) {
for(int i = 0; i < 5; i++) new Thread(new MyThread(i+1)).start();
}
}
兩種方法各有千秋,可以靈活運用。
Java把內存劃分成兩種:一種是棧內存,一種是堆內存。
在函數中定義的一些基本類型的變量和對象的引用變量都在函數的棧內存中分配。
當在一段代碼塊定義一個變量時,Java就在棧中為這個變量分配內存空間,當超過變量的作用域后,Java會自動釋放掉為該變量所分配的內存空間,該內存空間可以立即被另作他用。
堆內存用來存放由new建立的對象和數組。
在堆中分配的內存,由Java虛擬機的自動垃圾回收器來管理。
在堆中產生了一個數組或對象后,還可以在棧中定義一個特殊的變量,讓棧中這個變量的取值等于數組或對象在堆內存中的首地址,棧中的這個變量就成了數組或對象的引用變量。
引用變量就相當于是為數組或對象起的一個名稱,以后就可以在程序中運用棧中的引用變量來訪問堆中的數組或對象。
具體的說:
棧與堆都是Java用來在Ram中存放數據的地點。與C++不同,Java自動管理棧和堆,程序員不能直接地配置棧或堆。
Java的堆是一個運行時數據區,類的(對象從中分配空間。這些對象通過new、newarray、anewarray和multianewarray等 指令建立,它們不須要程序代碼來顯式的釋放。堆是由垃圾回收來負責的,堆的優勢是可以動態地分配內存大小,生存期也不必事先告訴編譯器,因為它是在運行時 動態分配內存的,Java的垃圾收集器會自動收走這些不再運用的數據。但缺點是,由于要在運行時動態分配內存,存取速度較慢。
棧的優勢是,存取速度比堆要快,僅次于寄存器,棧數據可以共享。但缺點是,存在棧中的數據大小與生存期必須是確定的,缺乏靈活性。棧中主要存放一些基本 類型的變量(,int, short, long, byte, float, double, boolean, char)和對象句柄。
棧有一個很主要的特殊性,就是存在棧中的數據可以共享。假設我們同時定義:
int a = 3;
int b = 3;
編譯器先處理int a = 3;首先它會在棧中建立一個變量為a的引用,然后查找棧中能不能有3這個值,如果沒找到,就將3存放進來,然后將a指向3。接著處理int b = 3;在建立完b的引用變量后,因為在棧中已經有3這個值,便將b直接指向3。這樣,就出現了a與b同時均指向3的情況。這時,如果再令a=4;那么編譯器 會重新搜索棧中能不能有4值,如果沒有,則將4存放進來,并令a指向4;如果已經有了,則直接將a指向這個地址。因此a值的改動不會影響到b的值。要留心這 種數據的共享與兩個對象的引用同時指向一個對象的這種共享是不同的,因為這種情況a的修改并不會影響到b, 它是由編譯器完成的,它有利于節省空間。而一個對象引用變量修改了這個對象的內部狀態,會影響到另一個對象引用變量。
String是一個特殊的包裝類數據。可以用:
String str = new String("abc");
String str = "abc";
兩種的形式來建立,第一種是用new()來新建對象的,它會在存放于堆中。每調用一次就會建立一個新的對象。
而第二種是先在棧中建立一個對String類的對象引用變量str,然后查找棧中有沒有存放"abc",如果沒有,則將"abc"存放進棧,并令str指向“abc”,如果已經有“abc” 則直接令str指向“abc”。
比較類里面的數值能不能相等時,用equals()要領;當測試兩個包裝類的引用能不能指向同一個對象時,用==,下面用例子說明上面的理論。
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true可以看出str1和str2是指向同一個對象的。
String str1 =new String ("abc");
String str2 =new String ("abc");
System.out.println(str1==str2); // false用new的方式是生成不同的對象。每一次生成一個。
因此用第二種方式建立多個“abc”字符串,在內存中其實只存在一個對象而已. 這種寫法有利與節省內存空間. 同時它可以在一定程度上提高程序的運行速度,因為JVM會自動根據棧中數據的實際情況來決定能不能有必要建立新對象。而對于String str = new String("abc");的代碼,則一概在堆中建立新對象,而不管其字符串值能不能相等,能不能有必要建立新對象,從而加重了程序的負擔。
另一方面, 要留心 : 我們在運用諸如String str = "abc";的格式定義類時,總是想當然地認為,建立了String類的對象str。擔心陷阱!對象可能并沒有被建立!而可能只是指向一個先前已經建立的 對象。只有通過new()要領才能保證每次都建立一個新的對象。 由于String類的immutable性質,當String變量須要經常變換其值時,應該考慮運用 StringBuffer類,以提高程序效率。
java中內存分配策略及堆和棧的比較
2.1 內存分配策略按照編譯原理的觀點,程序運行時的內存分配有三種策略,分別是靜態的,棧式的,和堆式的.靜態存儲分配是指在編譯時就能確定每個數據目標在運行時刻的存儲空間需求,因而在編譯時就可以給他們分配固定的內存空間.這種分配策略要求程序代碼中不允 許有可變數據結構(比如可變數組)的存在,也不允許有嵌套或者遞歸的結構出現,因為它們都會導致編譯程序不能計算準確的存儲空間需求.棧式存儲分配也可稱為動態存儲分配,是由一個類似于堆棧的運行棧來實現的.和靜態存儲分配相反,在棧式存儲方案中,程序對數據區的需求在編譯時是完全未知 的,只有到運行的時候才能夠知道,但是規定在運行中進入一個程序模塊時,必須知道該程序模塊所需的數據區大小才能夠為其分配內存.和我們在數據結構所熟知 的棧一樣,棧式存儲分配按照先進后出的原則執行 分配。
靜態存儲分配要求在編譯時能知道所有變量的存儲要求,棧式存儲分配要求在流程的入口處必須知道所有的存儲要求,而堆式存儲分配則專門負責在編譯時或運行時 模塊入口處都不能確定存儲要求的數據結構的內存分配,比如可變長度串和對象實例.堆由大片的可運用 塊或空閑塊組成,堆中的內存可以按照任意順序分配和釋 放.
2.2 堆和棧的比較
上面的定義從編譯原理的教材中總結而來,除靜態存儲分配之外,都顯得很呆板和難以理解,下面撇開靜態存儲分配,集中比較堆和棧:從堆和棧的功能和作用來通俗的比較,堆主要用來存放對象的,棧主要是用來執行程序的.而這種不同又主要是由于堆和棧的特點決定的:在編程中,例如C/C++中,所有的要領調用都是通過棧來執行 的,所有的局部變量,形式參數都是從棧中分配內存空間的。實際上也不是什么分配,只是從棧頂 向上用就行,就好像工廠中的傳送帶(conveyor belt)一樣,Stack Pointer會自動指引你到放東西的位置,你所要做的只是把東西放下來就行.退出函數的時候,修改棧指針就可以把棧中的內容銷毀.這樣的模式速度最快, 當然要用來運行程序了.須要留心的是,在分配的時候,比如為一個即將要調用的程序模塊分配數據區時,應事先知道這個數據區的大小,也就說是雖然分配是在程 序運行時執行 的,但是分配的大小多少是確定的,不變的,而這個"大小多少"是在編譯時確定的,不是在運行時.堆是使用程序在運行的時候請求操作系統分配給自己內存,由于從操作系統管理的內存分配,所以在分配和銷毀時都要占用時間,因此用堆的效率非常低.但是堆的 優點在于,編譯器不必知道要從堆里分配多少存儲空間,也不必知道存儲的數據要在堆里停留多長的時間,因此,用堆保存數據時會得到更大的靈活性。事實上,面 向對象的多態性,堆內存分配是必不可少的,因為多態變量所需的存儲空間只有在運行時建立了對象之后才能確定.在C++中,要求建立一個對象時,只需用 new命令編制有關的代碼即可。執行這些代碼時,會在堆里自動執行 數據的保存.當然,為達到這種靈活性,必然會付出一定的代價:在堆里分配存儲空間時會花 掉更長的時間!這也正是導致我們剛才所說的效率低的原由 ,看來列寧同志說的好,人的優點往往也是人的缺點,人的缺點往往也是人的優點.
2.3 JVM中的堆和棧JVM是基于堆棧的虛擬機.JVM為每個新建立的線程都分配一個堆棧.也就是說,對于一個Java程序來說,它的運行就是通過對堆棧的操作來完成的。堆棧以幀為單位保存線程的狀態。JVM對堆棧只執行 兩種操作:以幀為單位的壓棧和出棧操作。
我們知道,某個線程正在執行的要領稱為此線程的當前要領 .我們可能不知道,當前要領運用的幀稱為當前幀。當線程激活一個Java要領 ,JVM就會在線程的 Java堆棧里新壓入一個幀。這個幀自然成為了當前幀.在此要領執行期間,這個幀將用來保存參數,局部變量,中間計算流程和其他數據.這個幀在這里和編譯 原理中的活動紀錄的概念是差不多的.從Java的這種分配機制來看,堆棧又可以這樣理解:堆棧(Stack)是操作系統在建立某個進程時或者線程(在支持多線程的操作系統中是線程)為這個線程建立的存儲區域,該區域具有先進后出的特征。
每一個Java使用都唯一對應一個JVM實例,每一個實例唯一對應一個堆。使用程序在運行中所建立的所有類實例或數組都放在這個堆中,并由使用所有的線程 共享.跟C/C++不同,Java中分配堆內存是自動原始化的。Java中所有對象的存儲空間都是在堆中分配的,但是這個對象的引用卻是在堆棧中分配,也 就是說在建立一個對象時從兩個地點都分配內存,在堆中分配的內存實際建立這個對象,而在堆棧中分配的內存只是一個指向這個堆對象的指針(引用)而已。
要求:
1、完成一個對水果倉庫管理的簡單系.。
2、完成,增加、查詢、修改簡單的操作。
分析:
1、首先我們要有進行分成分析 表層----操作層----底層;
2、表層有什么 :可供操作的選項即(增、查、改);
3、操作層有什么:完成不同的操作(讀文件和寫文件);
4、底層有什么:完成數據的寫出和讀入;
步驟:
先完成如下javaproject的創建:

//下面為每個類中的具體內容(按我做改程序的順須寫的)
//Fruit
package VO;
import java.io.Serializable;
@SuppressWarnings("serial")
public class Fruit implements Serializable {
//屬性
private String name;
private String area;
private float kg;
//構造方法
public Fruit(){}
public Fruit(String name,String area,float kg){
this.name =name;
this.area =area;
this.kg =kg;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getArea() {
return area;
}
public void setArea(String area) {
this.area = area;
}
public float getKg() {
return kg;
}
public void setKg(float kg) {
this.kg = kg;
}
public String toString (){
return "水果名:"+this.name +" 源產地:"+this.area+" 現重量:"+this.kg ;
}
}
//主方法
package Main;
import Menu.Menu;
public class Main {
//主方法
public static void main(String[] args){
System.out.println("簡單的水果倉庫管理系統");
//調用Menu方法
new Menu();
}
}
//Menu
package Menu;
import OP.FruitOperate;
import Util.InputDate;
public class Menu {
InputDate input= null;
public Menu(){
this.input=new InputDate();
//循環出現菜單
while (true){
this.show();
}
}
//需要定義的菜單內容
private void show() {
System.out.println("\t\t\t1、增加水果庫存");
System.out.println("\t\t\t2、瀏覽庫存信息");
System.out.println("\t\t\t3、修改庫存信息");
System.out.println("\t\t\t4、注銷管理系統");
System.out.print("\n\n請選擇您要使用的操作:");
int temp = input.getInt();
switch(temp){
case 1:{ // 增加水果庫存
new FruitOperate().add(); //業務處理層
break;
}
case 2:{ // 瀏覽庫存信息
new FruitOperate().show();
break;
}
case 3:{ // 修改庫存信息
new FruitOperate().update();
break;
}
case 4:{ //注銷管理系統
System.out.println("注銷中******************");
System.out.println("注銷成功!");
System.exit(1);
}
default:{ //錯誤信息提示
System.out.println("請選擇正確的操作范圍如下:");
break;
}
}
}
}
//對度入數據的相關操作
package Util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class InputDate {
private BufferedReader buf =null;
public InputDate(){
buf = new BufferedReader(new InputStreamReader(System.in));
};
public String getString(){
String str = null;
try {
str = buf.readLine();
} catch (IOException e) {}
return str;
}
public int getInt(){
int temp = 0;
//如果輸入的不是數字,告訴用戶輸入錯了~
//可以使用正則驗證
String str = null;
boolean flag = true;
while(flag){
//輸入數據
str = this.getString();
if (!(str.matches("\\d+"))){
//如果輸入的不是一個數字,則必須重新輸入
System.out.print("輸入的內容必須是上面操作代號的范圍,請重新輸入:");
}else{
//輸入的是一個正確的數字,則可以進行轉換
temp = Integer.parseInt(str);
//表示退出循環
flag = false;
}
}
return temp;
}
public float getFloat() {
float f = 0.0f;
//如果輸入的不是數字,提示告訴用戶輸入錯了~
//可以使用正則驗證
String str = null;
boolean flag = true;
while(flag){
//輸入數據
str = this.getString();
if (!(str.matches("\\d+?.\\d{1,2}"))){
//如果輸入的不是一個數字,則必須重新輸入
System.out.print("輸入的內容必須是小數(小數點后兩位),請重新輸入:");
}else{
//輸入的是一個正確的數字,則可以進行轉換
f = Float.parseFloat(str);
//表示退出循環
flag = false;
}
}
return f;
}
}
///實現管理的方法類
package OP;
import Util.FileOperate;
import Util.InputDate;
import VO.Fruit;
public class FruitOperate {
private InputDate input = null;
public FruitOperate(){
this.input = new InputDate();
}
//完成具體的Fruit對象操作
public void add(){
//要使用輸入數據的類
String name = null;
String area = null;
float kg = 0.0f;
System.out.print("輸入水果名:");
name = this.input.getString();
System.out.print("輸入源產地:");
area = this.input.getString();
System.out.print("輸入入庫量:");
kg = this.input.getFloat();
//生成Fruit對象,把對象保存在文件中
Fruit f = new Fruit(name,area,kg);
try{
new FileOperate().save(f); //io操作層
System.out.println("數據保存成功!");
}catch(Exception e){
System.out.println("數據保存失敗!");
}
}
public void show(){
//從文件中把內容讀進來
Fruit f = null;
try{
f = (Fruit) new FileOperate().read();
}catch(Exception e){
System.out.println("內容顯示失敗,請確定數據是否存在!");
}
if(f != null){
System.out.println(f);
}
}
public void update(){
//先將之前的信息查出來
Fruit f = null;
try{
f = (Fruit) new FileOperate().read();
}catch(Exception e){
System.out.println("內容顯示失敗,請確定數據是否存在!");
}
if(f != null){
String name = null;
String area = null;
float kg =0.0f;
System.out.print("請輸入新的水果名(原水果名:"+f.getName()+")");
name = this.input.getString();
System.out.print("請輸入新的源產地(原源產地:"+f.getArea()+")");
area = this.input.getString();
System.out.print("請輸入新的庫總量(原庫總量:"+f.getKg()+")");
kg = this.input.getFloat();
//信息重新設置
f.setName(name);
f.setArea(area);
f.setKg(kg);
try{
new FileOperate().save(f);
System.out.println("數據更新成功!");
}catch(Exception e){
System.out.println("數據更新失敗!");
}
}
}
}
//底層操作 文件的讀入和讀出
package Util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class FileOperate {
public static final String FILENAME = "E:\\fruit.txt";
//把對象保存在文件之中
public void save(Object obj){
ObjectOutputStream out = null;
try {
out = new ObjectOutputStream(new FileOutputStream(new File(FILENAME)));
//寫入對象
out.writeObject(obj);
}catch(Exception e){
try {
throw e;
} catch (Exception e1) {}
}finally {
try {
out.close();
}catch(Exception e){}
}
}
//把對象從文件之中讀出來
public Object read() throws Exception{
Object obj = null;
ObjectInputStream input =null;
try {
input = new ObjectInputStream(new FileInputStream(new File(FILENAME)));
obj = input.readObject();
} catch (Exception e) {
throw e;
}finally{
try{
input.close();
}catch(Exception e){}
}
return obj;
}
}
運行結果如下:


這篇文章只是一個原理 ,感謝閱讀 希望能夠提供寶貴意見!QQ:237333696
該程序是很簡單 只是把我上一個程序可視化希望能給初學java的人提供幫助!!!
//stock
package StockUI;
public class Stock {
private int id; //
private String name; //
private int price; //
private int flag; //
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int getFlag() {
return flag;
}
public void setFlag(int flag) {
this.flag = flag;
}
}
//服務器端
package StockUI;
import java.util.Random;
public class StockServer {
public static void main(String[] args){
Stock sk[] = getStock();
for(int i=0;i<sk.length;i++){
if(sk[i] != null){
System.out.println("name = " + sk[i].getPrice());
}
}
}
public static Stock[] getStock(){
Stock stock[] = new Stock[3];
//#####################################################
Stock sk = new Stock();
sk.setId(1);
sk.setName("ibm");
Random rd = new Random();
sk.setPrice(rd.nextInt(100));
sk.setFlag(1);
stock[0] = sk;
//#######################################################
Stock sk1 = new Stock();
sk1.setId(2);
sk1.setName("sun");
sk1.setPrice(rd.nextInt(100));
sk1.setFlag(1);
stock[1] = sk1;
//######################################################
Stock sk2 = new Stock();
sk2.setId(3);
sk2.setName("oracle");
sk2.setPrice(rd.nextInt(100));
sk2.setFlag(1);
stock[2] = sk2;
return stock;
}
}
package StockUI;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
public class StockUI {
private TableEditor editor = null;
private Table table = null;
public static void main(String[] args) {
new StockUI();
}
private StockUI() {
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
shell.setText("大智慧股票模擬系統");
createTable(shell,display);
shell.pack(); //窗口變大
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
/**
* 創建表格
*
* @param shell
*/
private void createTable(final Shell shell,final Display display) {
table = new Table(shell, SWT.MULTI | SWT.FULL_SELECTION);
editor = new TableEditor(table);
editor.horizontalAlignment = SWT.LEFT;
editor.grabHorizontal = true;
table.setHeaderVisible(true);
table.setLinesVisible(true);
TableColumn col1 = new TableColumn(table, SWT.LEFT);
col1.setText("股票代碼");
col1.setWidth(100);
TableColumn col2 = new TableColumn(table, SWT.LEFT);
col2.setText("公司名");
col2.setWidth(100);
TableColumn col5 = new TableColumn(table, SWT.LEFT);
col5.setText("現價");
col5.setWidth(100);
TableColumn col3 = new TableColumn(table, SWT.LEFT);
col3.setText("漲幅");
col3.setWidth(100);
TableColumn col4 = new TableColumn(table, SWT.LEFT);
col4.setText("換手率");
col4.setWidth(100);
/**
* 添加表格數據
*/
Stock[] sk = StockServer.getStock();
final TableItem[] itemArr = new TableItem[sk.length];
for(int i=0;i<itemArr.length;i++){
itemArr[i] = new TableItem(table, SWT.LEFT);
}
final int time=1000;
Runnable showTime = new Runnable(){
public void run(){
Stock[] sk = StockServer.getStock();
for(int i=0;i<itemArr.length;i++){
itemArr[i].setText(new String[] { String.valueOf(sk[i].getId()), String.valueOf(sk[i].getName()), String.valueOf(sk[i].getPrice())
});
}
display.timerExec(time, this);
}
};
display.timerExec(time,showTime);//你的swt程序的display
// 刪除菜單
Menu menu1 = new Menu(shell, SWT.POP_UP);
table.setMenu(menu1);
MenuItem menuitem1 = new MenuItem(menu1, SWT.PUSH);
menuitem1.setText("刪除");
menuitem1.addListener(SWT.Selection, new Listener() {
@Override
public void handleEvent(Event event) {
MessageBox mbox = new MessageBox(shell, SWT.DIALOG_TRIM|SWT.ICON_INFORMATION);
mbox.setText("刪除成功");
mbox.setMessage("刪除了" + table.getSelectionCount() + "條記錄");
table.remove(table.getSelectionIndices());
mbox.open();
}
});
// 修改table
{}
}
}
//運行結果如下:
不同時段 不同結果
|