2009年9月22日星期二

Sheet里行的移动

如果要移动某一行的话,可以使用「HSSFSheet」类的「shiftRows」方法。
shiftRows
public void shiftRows(int startRow, int endRow, int n)
Shifts rows between startRow and endRow n number of rows. If you use 
a negative number, it will shift rows up. Code ensures that rows don't
wrap around. Calls shiftRows(startRow, endRow, n, false, false); 
 
Additionally shifts merged regions that are completely defined in 
these rows (ie. merged 2 cells on a row to be shifted). 
 
Parameters:
  startRow - the row to start shifting
  endRow - the row to end shifting
   n - the number of rows to shift
指定要移动的行的范围从「startRow」行到「endRow」行。「n」如果是正数就往下移动,如果为负,就往上移动。

示例程序

按下图准备一个Excel文件。























import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
 
public class POISample{
  public static void main(String[] args){
    FileInputStream in = null;
    HSSFWorkbook workbook = null;
 
    try{
      in = new FileInputStream("sample.xls");
      POIFSFileSystem fs = new POIFSFileSystem(in);
      workbook = new HSSFWorkbook(fs);
    }catch(IOException e){
      System.out.println(e.toString());
    }finally{
      try{
        in.close();
      }catch (IOException e){
        System.out.println(e.toString());
      }
    }
 
    HSSFSheet sheet = workbook.getSheetAt(0);
 
    sheet.shiftRows(1, 2, 2);
 
    FileOutputStream out = null;
    try{
      out = new FileOutputStream("sample2.xls");
      workbook.write(out);
    }catch(IOException e){
      System.out.println(e.toString());
    }finally{
      try {
        out.close();
      }catch(IOException e){
        System.out.println(e.toString());
      }
    }
  }
}
打开新建的Sample2.xls文件看看。























从上图可以看出,第二行和第三行的内容已经移动到第四行和第五行,并覆盖原第四行和第五行的内容。但第二行到第五行的行高却维持原样没有变化。
再来看看有没有办法可以既移动内容,又可以移动行高呢?从帮助文档里可以看出,对于「shiftRows」方法,还有另外一种用法。
shiftRows
public void shiftRows(int startRow, int endRow, int n,
              boolean copyRowHeight, boolean resetOriginalRowHeight)
Shifts rows between startRow and endRow n number of rows. If you use 
a negative number, it will shift rows up. Code ensures that rows don't
wrap around 
 
Additionally shifts merged regions that are completely defined in these
rows (ie. merged 2 cells on a row to be shifted). 
 
TODO Might want to add bounds checking here 
 
Parameters:
  startRow - the row to start shifting
  endRow - the row to end shifting
  n - the number of rows to shift
  copyRowHeight - whether to copy the row height during the shift
  resetOriginalRowHeight - whether to set the original row's height
    to the default
前面3个参数和之前一样。如要使行高也一起移动的话,设置「copyRowHeight」参数为「true」。
还有,移动后,原来的行是保留原行高不变还是恢复到默认行高呢?可以设置「resetOriginalRowHeight」参数。为「true」时,则可以恢复到默认行高。反之则保留原行高不变。

示例程序

import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
 
public class POISample{
  public static void main(String[] args){
    FileInputStream in = null;
    HSSFWorkbook workbook = null;
 
    try{
      in = new FileInputStream("sample.xls");
      POIFSFileSystem fs = new POIFSFileSystem(in);
      workbook = new HSSFWorkbook(fs);
    }catch(IOException e){
      System.out.println(e.toString());
    }finally{
      try{
        in.close();
      }catch (IOException e){
        System.out.println(e.toString());
      }
    }
 
    HSSFSheet sheet = workbook.getSheetAt(0);
 
    sheet.shiftRows(1, 2, 2, true, true);
 
    FileOutputStream out = null;
    try{
      out = new FileOutputStream("sample2.xls");
      workbook.write(out);
    }catch(IOException e){
      System.out.println(e.toString());
    }finally{
      try {
        out.close();
      }catch(IOException e){
        System.out.println(e.toString());
      }
    }
  }
}
再打开新生成的Sample2.xls文件来看看。






















从上图可以看出,移动后,原行高也被移动了,而原行则恢复到默认行高。

2009年9月20日星期日

Sheet里行的读取


要取得Sheet里的某一行,可以使用「HSSFSheet」类的「getRow」方法。
getRow
public HSSFRow getRow(int rownum)
Returns the logical row (not physical) 0-based. If you ask for a row 
that is not defined you get a null. This is to say row 4 represents 
the fifth row on a sheet. 
 
Parameters:
  rownum - row to get 
Returns:
  HSSFRow representing the rownumber or null if its not defined on the 
    sheet
利用行号取得指定的行。如果行不存在,则返回NULL。

示例程序

动手做做看。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
 
public class POISample{
  public static void main(String[] args){
    HSSFWorkbook workbook = new HSSFWorkbook();
 
    HSSFSheet sheet = workbook.createSheet();
 
    HSSFRow row = sheet.createRow(1);
 
    for (int i = 0 ; i < 3 ; i++){
      HSSFRow r = sheet.getRow(i);
      if (r  == null){
        System.out.println("第" + i + "行不存在。");
      }else{
        System.out.println("第" + i + "行取得成功。");
      }
    }
  }
}
上面的程序里,先创建一个Sheet,然后创建第二行(行号为1)。最后读取第一行到第三行的三行。结果如下。

第0行不存在。
第1行取得成功。
第2行不存在。
这和予想的一样。

读取有值的行

按照下图准备一个Excel文件。



import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
 
public class POISample{
  public static void main(String[] args){
    FileInputStream in = null;
    HSSFWorkbook workbook = null;
 
    try{
      in = new FileInputStream("sample.xls");
      POIFSFileSystem fs = new POIFSFileSystem(in);
      workbook = new HSSFWorkbook(fs);
    }catch(IOException e){
      System.out.println(e.toString());
    }finally{
      try{
        in.close();
      }catch (IOException e){
        System.out.println(e.toString());
      }
    }
 
    HSSFSheet sheet = workbook.getSheetAt(0);
 
    for (int i = 0 ; i < 3 ; i++){
      HSSFRow r = sheet.getRow(i);
      if (r  == null){
        System.out.println("第" + i + "行不存在。");
      }else{
        System.out.println("第" + i + "行取得成功。");
      }
    }
  }
}
结果如下。
第0行取得成功。
第1行取得成功。
第2行不存在。
从上面的例子可以看出,如果当前行有值的话,那么读取这一行时肯定存在。

从取得的行里获取单元格的值。

这一次从已经取得的行里获取单元格的值。仍然使用刚才的Excel文件。用getRow方法先取得行对象,再从单元格里获取值。
import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
 
public class POISample{
  public static void main(String[] args){
    FileInputStream in = null;
    HSSFWorkbook workbook = null;
 
    try{
      in = new FileInputStream("sample.xls");
      POIFSFileSystem fs = new POIFSFileSystem(in);
      workbook = new HSSFWorkbook(fs);
    }catch(IOException e){
      System.out.println(e.toString());
    }finally{
      try{
        in.close();
      }catch (IOException e){
        System.out.println(e.toString());
      }
    }
 
    HSSFSheet sheet = workbook.getSheetAt(0);
 
    HSSFRow row = sheet.getRow(1);
 
    HSSFCell cell = row.getCell((short)1);
    System.out.println(cell.getStringCellValue());
  }
}
结果如下。
sample
可以看出,把第二行第二列的值取出来了。

在现有的行上创建行

最后,再来试试看,在现有的行上,用「createRow」方法创建一行看看会是什么结果。还是使用刚才的Excel文件,在第二行上创建一行,再把值取出来。
import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
 
public class POISample{
  public static void main(String[] args){
    FileInputStream in = null;
    HSSFWorkbook workbook = null;
 
    try{
      in = new FileInputStream("sample.xls");
      POIFSFileSystem fs = new POIFSFileSystem(in);
      workbook = new HSSFWorkbook(fs);
    }catch(IOException e){
      System.out.println(e.toString());
    }finally{
      try{
        in.close();
      }catch (IOException e){
        System.out.println(e.toString());
      }
    }
 
    HSSFSheet sheet = workbook.getSheetAt(0);
 
    HSSFRow row = sheet.createRow(1);
 
    HSSFCell cell = row.getCell((short)1);
 
    System.out.println(cell.getStringCellValue());
  }
}
结果如下。
Exception in thread "main" java.lang.NullPointerException
        at POISample.main(POISample.java:35)
发生了空指针异常。本来对于已经存在的行用「createRow」方法进行创建行操作,可能你会以为会复制原来的行,但事实并非如此。
让我们在原来程序的基础上再稍作一些变化,已经存在的行用「createRow」方法进行创建行操作后,再在该行的空白单元格设上值,保存为新的文件。
import java.io.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
 
public class POISample{
  public static void main(String[] args){
    FileInputStream in = null;
    HSSFWorkbook workbook = null;
 
    try{
      in = new FileInputStream("sample.xls");
      POIFSFileSystem fs = new POIFSFileSystem(in);
      workbook = new HSSFWorkbook(fs);
    }catch(IOException e){
      System.out.println(e.toString());
    }finally{
      try{
        in.close();
      }catch (IOException e){
        System.out.println(e.toString());
      }
    }
 
    HSSFSheet sheet = workbook.getSheetAt(0);
 
    HSSFRow row = sheet.createRow(1);
 
    HSSFCell cell = row.createCell((short)3);
    cell.setCellValue("news");
 
    FileOutputStream out = null;
    try{
      out = new FileOutputStream("sample2.xls");
      workbook.write(out);
    }catch(IOException e){
      System.out.println(e.toString());
    }finally{
      try {
        out.close();
      }catch(IOException e){
        System.out.println(e.toString());
      }
    }
  }
}
执行上面程序后,打开新的Excel文件如下。























对于已经存在的行再用「createRow」方法执行的话,那从原来行里有值的单元格取值时会发生空指针异常。但如果新创建一个单元格再设值的话,那之前单元格的值也会被保留下来。虽然是猜测,不过大家可以自己亲自动手来验证一下。

Sheet里行的创建

之前仅仅新建了Sheet,虽然可以看到新建的Sheet里有无数的单元格,但还不能直接往这些单元格设值。要想往这些单元格里设值,你还必须创建行。
因此,再来看看行创建的方法。
在Sheet里创建行,使用「HSSFSheet」类的「createRow」方法。
createRow
public HSSFRow createRow(int rownum)
Create a new row within the sheet and return the high level representation 
 
Parameters:
  rownum - row number 
Returns:
  High level HSSFRow object representing a row in the sheet
创建指定行号的行。行号是从0开始的整数,最大是65535。创建行所返回的值是「HSSFRow」类对象,关于「HSSFRow」类定义的说明,以后再详细说。
创建方法很多,要说详细挺复杂。比方说,即使第一行(行号为0)和第二行不创建,也能直接创建第三行。

示例程序

亲自动手做一下吧。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;
 
public class POISample{
  public static void main(String[] args){
    HSSFWorkbook workbook = new HSSFWorkbook();
 
    HSSFSheet sheet = workbook.createSheet();
 
    HSSFRow row = sheet.createRow(2);
 
    /* 下記はセルを作成し、セルに値を代入しています */
    HSSFCell cell = row.createCell((short)0);
    cell.setCellValue("test");
 
    FileOutputStream out = null;
    try{
      out = new FileOutputStream("sample.xls");
      workbook.write(out);
    }catch(IOException e){
      System.out.println(e.toString());
    }finally{
      try {
        out.close();
      }catch(IOException e){
        System.out.println(e.toString());
      }
    }
  }
}
在上面的程序里,生成一个Sheet,然后单独创建了第三行(行号为2),接着又创建了一个单元格,最后给这个单元格设了值。执行后,打开「sample.xls」文件看看。






















可以看到,在第三行第一列,值已经被设定好了。

HSSFSheet类定义

用POI来作成一个Sheet,可以用「HSSFSheet」类,它的类定义如下。
  • java.lang.Object
  • org.apache.poi.hssf.usermodel.HSSFSheet
  • public class HSSFSheet extends java.lang.Object
它有两个构造方法。
构建器
protected HSSFSheet(Workbook book)
Creates new HSSFSheet - called by HSSFWorkbook to create a sheet from scratch.
protected HSSFSheet(Workbook book, Sheet sheet)
Creates an HSSFSheet representing the given Sheet object.
虽然有两个构建器,但都是protected的,所以要新建Sheet,只能通过Workbook。

新建Sheet

在Workbook里新建Sheet时,还是使用「HSSFWorkbook」类的「createSheet」的方法,详细可以参照「在Workbook里创建Sheet」。
使用方法如下。
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();

读取现有的Sheet

对于在Workbook已经存在的Sheet来说,可以用「HSSFWorkbook」类的「getSheet」方法来读取。
getSheet
public HSSFSheet getSheet(java.lang.String name)
Get sheet with the given name 
 
Parameters:
  name - of the sheet 
Returns:
  HSSFSheet with the name provided or null if it does not exist

参数为Sheet名称。
使用方法如下。
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.getSheet("sheet1")
不用Sheet名而用Sheet的序列号来取得Sheet的话,可以用「HSSFWorkbook」类的「getSheetAt」方法。
getSheetAt
public HSSFSheet getSheetAt(int index)
Get the HSSFSheet object at the given index. 
 
Parameters:
  index - of the sheet number (0-based physical & logical) 
Returns:
  HSSFSheet at the provided index
使用方法如下。
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.getSheetAt(1);

改变Sheet名称

要改变现有Sheet或刚新建Sheet的名称,可以用「HSSFWorkbook」类的「setSheetName」方法。
setSheetName
public void setSheetName(int sheet, java.lang.String name)
set the sheet name. Will throw IllegalArgumentException if the name 
is greater than 31 chars or contains /\?*[] 
 
Parameters:
  sheet - number (0 based)
指定要改变的Sheet的序列号。设置名称时,最大长度是31个文字,还有「/\?*[]」这样的字符不能使用。
指定汉字Sheet名时,用第二个方法。
setSheetName
public void setSheetName(int sheet, java.lang.String name, short encoding)
--
「encoding」的参数在「HSSFWorkbook」类里被定义成下面两种。
static byte ENCODING_COMPRESSED_UNICODE
static byte ENCODING_UTF_16
设定汉字时(包括日语),「encoding」的参数应该传入「HSSFWorkbook.ENCODING_UTF_16」。

示例程序

亲自动手做一做吧。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 
public class POISample{
  public static void main(String[] args){
    HSSFWorkbook workbook = new HSSFWorkbook();
 
    workbook.createSheet();
    workbook.createSheet();
 
    workbook.setSheetName(0, "test");
    workbook.setSheetName(1, "テスト", HSSFWorkbook.ENCODING_UTF_16);
 
    FileOutputStream out = null;
    try{
      out = new FileOutputStream("sample.xls");
      workbook.write(out);
    }catch(IOException e){
      System.out.println(e.toString());
    }finally{
      try {
        out.close();
      }catch(IOException e){
        System.out.println(e.toString());
      }
    }
  }
}
程序执行后,打开「sample1.xls」文件来看看。


可以看出,汉字Sheet名被正常设好了。

使用「createSheet」方法创建新的Sheet时,不能进行encoding设定。所以要设置汉字Sheet名时,只能先新建一个Sheet,然后再对该Sheet进行改名操作。

在Workbook里复制Sheet

要复制Workbook里现有的Sheet来创建新的Sheet,可以使用「HSSFWorkbook」类的「cloneSheet」方法。
cloneSheet
public HSSFSheet cloneSheet(int sheetNum)
create an HSSFSheet from an existing sheet in the HSSFWorkbook. 
 
Returns:
  HSSFSheet representing the cloned sheet.
指定要复制的Sheet序列号。

示例程序

再一次动手来做做吧。复制前Workbook如下。










































import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
 
public class POISample{
  public static void main(String[] args){
    FileInputStream in = null;
    HSSFWorkbook workbook = null;
 
    try{
      in = new FileInputStream("sample.xls");
      POIFSFileSystem fs = new POIFSFileSystem(in);
      workbook = new HSSFWorkbook(fs);
    }catch(IOException e){
      System.out.println(e.toString());
    }finally{
      try{
        in.close();
      }catch (IOException e){
        System.out.println(e.toString());
      }
    }
 
    workbook.cloneSheet(0);
    workbook.cloneSheet(1);
 
    FileOutputStream out = null;
    try{
      out = new FileOutputStream("sample.xls");
      workbook.write(out);
    }catch(IOException e){
      System.out.println(e.toString());
    }finally{
      try {
        out.close();
      }catch(IOException e){
        System.out.println(e.toString());
      }
    }
  }
}
执行后打开「sample1.xls」文件看看。





















可以看出,两个Sheet被成功复制。被复制的Sheet名格式是「原Sheet名(序列号)」。顺便一提的是,如果你手动在Excel里进行复制的话,被复制的Sheet名的格式是「原Sheet名 (序列号)」。也就是原Sheet名和(序列号)之间有一个半角空格。

从Workbook删除Sheet

要从Workbook里删除Sheet,可以使用「HSSFWorkbook」类的方法「removeSheetAt」。
removeSheetAt
public void removeSheetAt(int index)
removes sheet at the given index 
 
Parameters:
  index - of the sheet (0-based)
指定要删除Sheet的序列号。
如果不知道序列号的话,也可以通过「HSSFWorkbook」类的方法「getSheetIndex」,设定Sheet名来取得序列号。
getSheetIndex
public int getSheetIndex(java.lang.String name)
Returns the index of the sheet by his name 
 
Parameters:
  name - the sheet name 
Returns:
  index of the sheet (0 based)
参数请指定要删除的Sheet名。

示例程序

生成一个Workbook,再在其中创建三个Sheet,最后再把名为「Sheet1」的Sheet删除。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 
public class POISample{
  public static void main(String[] args){
    HSSFWorkbook workbook = new HSSFWorkbook();
 
    workbook.createSheet();
    workbook.createSheet();
    workbook.createSheet();
 
    workbook.removeSheetAt(workbook.getSheetIndex("Sheet1"));
 
    System.out.println("Sheet0 = " + workbook.getSheetIndex("Sheet0"));
    System.out.println("Sheet2 = " + workbook.getSheetIndex("Sheet2"));
 
    FileOutputStream out = null;
    try{
      out = new FileOutputStream("sample.xls");
      workbook.write(out);
    }catch(IOException e){
      System.out.println(e.toString());
    }finally{
      try {
        out.close();
      }catch(IOException e){
        System.out.println(e.toString());
      }
    }
  }
}
示例程序执行后,会生成「sample1.xls」这样的文件,打开来看看先。



















从图中可以看出,Sheet1被删除了,那么这时候序列号又是怎么样的呢?你还是可以通过「HSSFWorkbook」类的方法「getSheetIndex」,设定Sheet名来取得序列号看看。

Sheet0 = 0
Sheet2 = 1

我们发现中间的Sheet被删除后,后面的Sheet序列号会往前移一个,总之会维持从0开始的整数顺序。

在Workbook里创建Sheet

要在Workbook里创建一个Sheet,可以使用「HSSFWorkbook」类的「createSheet」方法。
createSheet
public HSSFSheet createSheet()
create an HSSFSheet for this HSSFWorkbook, adds it to the sheets and 
returns the high level representation. Use this to create new sheets. 
 
Returns:
  HSSFSheet representing the new sheet.
还有一个名称相同的「createSheet」方法,但可以指定Sheet名。
createSheet
public HSSFSheet createSheet(java.lang.String sheetname)
create an HSSFSheet for this HSSFWorkbook, adds it to the sheets and 
returns the high level representation. Use this to create new sheets. 
 
Parameters:
  sheetname - sheetname to set for the sheet. 
Returns:
  HSSFSheet representing the new sheet.
创建的Sheet作为「HSSFSheet」类对象返回。

示例程序

import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 
public class POISample{
  public static void main(String[] args){
    HSSFWorkbook workbook = new HSSFWorkbook();
 
    workbook.createSheet();
    workbook.createSheet();
    workbook.createSheet("test");
 
    FileOutputStream out = null;
    try{
      out = new FileOutputStream("sample.xls");
      workbook.write(out);
    }catch(IOException e){
      System.out.println(e.toString());
    }finally{
      try {
        out.close();
      }catch(IOException e){
        System.out.println(e.toString());
      }
    }
  }
}
上面的示例程序执行后,会生成下面的「sample1.xls」文件。




















如果没有设定Sheet名,会从0开始默认设定为Sheet0,Sheet1等,设定为test的话,则可以创建test这样的Sheet。

2009年9月19日星期六

打开一个Workbook

这次我们用POI打开一个已经存在的Workbook。因为没有现成的方法,所以只能再次利用HSSFWorkbook构造方法
HSSFWorkbook
public HSSFWorkbook(POIFSFileSystem fs) throws java.io.IOException
--
这个构建器虽然没什么说明,但可以看出它的参数是一个「POIFSFileSystem」这样的一个类对象。那我们再来看看「POIFSFileSystem」类定义。

POIFSFileSystem类定义

「POIFSFileSystem」类对象可以把Excel文件作为数据流来进行传入传出。
  • java.lang.Object
  • org.apache.poi.poifs.filesystem.POIFSFileSystem
  • public class POIFSFileSystem extends java.lang.Object implements POIFSViewable
「POIFSFileSystem」类有两个构建器
构建器
POIFSFileSystem()
Constructor, intended for writing
POIFSFileSystem(java.io.InputStream stream)
Create a POIFSFileSystem from an InputStream
读取文件时使用第二个构建器。
POIFSFileSystem
public POIFSFileSystem(java.io.InputStream stream) throws java.io.IOException
Create a POIFSFileSystem from an InputStream 
 
Parameters:
  stream - the InputStream from which to read the data 
Throws: 
  java.io.IOException - on errors reading, or on invalid data
参数设定为读入Excel文件的流对象「InputStream」。使用方法如下。
FileInputStream in = new FileInputStream("sample.xls");
POIFSFileSystem fs = new POIFSFileSystem(in);
HSSFWorkbook wb = new HSSFWorkbook(fs);

通过POIFSFileSystem读取Excel文件

下面就实际做一下如何读取Excel文件。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
 
public class POISample{
  public static void main(String[] args){
    FileInputStream in = null;
    HSSFWorkbook workbook = null;
 
    try{
      in = new FileInputStream("sample1.xls");
      POIFSFileSystem fs = new POIFSFileSystem(in);
      workbook = new HSSFWorkbook(fs);
    }catch(IOException e){
      System.out.println(e.toString());
    }finally{
      try{
        in.close();
      }catch (IOException e){
        System.out.println(e.toString());
      }
    }
 
    FileOutputStream out = null;
    try{
      out = new FileOutputStream("sample2.xls");
      workbook.write(out);
    }catch(IOException e){
      System.out.println(e.toString());
    }finally{
      try {
        out.close();
      }catch(IOException e){
        System.out.println(e.toString());
      }
    }
  }
}
这个示例程序的作用是读取「sample1.xls」文件后再把它作为「sample2.xls」保存。
「sample1.xls」文件如下。






















实行之后,会生成一模一样的文件「sample2.xls」。
打开如下。


HSSFWorkbook类文件

首先从Workbook开始我们的POI编程之旅。要生成一个Workbook,需要用到HSSFWorkbook类文件,类定义如下:
  • java.lang.Object
  • org.apache.poi.hssf.usermodel.HSSFWorkbook
  • public class HSSFWorkbook extends java.lang.Object
它有五个构造方法:
构建器
HSSFWorkbook()
Creates new HSSFWorkbook from scratch (start here!)
HSSFWorkbook(java.io.InputStream s)
HSSFWorkbook(java.io.InputStream s, boolean preserveNodes)
Companion to HSSFWorkbook(POIFSFileSystem), this constructs the POI filesystem around your inputstream.
HSSFWorkbook(POIFSFileSystem fs)
HSSFWorkbook(POIFSFileSystem fs, boolean preserveNodes)
given a POI POIFSFileSystem object, read in its Workbook and populate the high and low level models.
我们用第一个构建器来生成一个Workbook
HSSFWorkbook
public HSSFWorkbook()
Creates new HSSFWorkbook from scratch (start here!)
使用方法如下:
HSSFWorkbook workbook = new HSSFWorkbook();
接下来再来对生成的Workbook进行保存操作,保存操作用「HSSFWorkbook」类的「write」方法。
write
public void write(java.io.OutputStream stream) throws java.io.IOException
Method write - write out this workbook to an Outputstream. Constructs
a new POI POIFSFileSystem, passes in the workbook binary representation
and writes it out. 
 
Parameters:
  stream - - the java OutputStream you wish to write the XLS to 
Throws: 
  java.io.IOException - if anything can't be written.
参数是作为保存对象的输出流对象「OutputStream」。

示例程序

可以自己实际做一下啊。
import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 
public class POISample{
  public static void main(String[] args){
    HSSFWorkbook workbook = new HSSFWorkbook();
 
    FileOutputStream out = null;
    try{
      out = new FileOutputStream("sample.xls");
      workbook.write(out);
    }catch(IOException e){
      System.out.println(e.toString());
    }finally{
      try {
        out.close();
      }catch(IOException e){
        System.out.println(e.toString());
      }
    }
  }
}
运行刚才的示例程序来生成一个Excel文件吧。

编译和运行方法

          下面先简单介绍一下,如何利用POI开发包对我们编写的JAVA程序进行编译和运行。

           编译的时候,必须要设置classpath,就是之前解压缩的poi-3.2-FINAL-20081019.jar文件的绝对路径。

javac -classpath F:\poi-3.2-FINAL\poi-3.2-FINAL-20081019.jar Sample.java

          实行的时候,也要设置classpath。

java -classpath F:\poi-3.2-FINAL\poi-3.2-FINAL-20081019.jar ;. Sample

          下面我们就通过一个简单的例子,来看看如何用POI生成一个Excel文件。

import java.io.*;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

public class POISample{

     public static void main(String[] args){
           HSSFWorkbook workbook = new HSSFWorkbook();

           FileOutputStream out = null;

           try{
                 out = new FileOutputStream("sample.xls");
                 workbook.write(out);
           }catch(IOException e){
                 System.out.println(e.toString());
           }finally{

                 try {
                       out.close();
                 }catch(IOException e){
                       System.out.println(e.toString());
                 }
           }
      }
}

        通过前面说的方法运行这个简单的JAVA代码的话,就能生成一个Sample.xls文件,不信就来试试吧。

2009年9月16日星期三

JAKARTA-POI的安装

       首先从Apache网站(http://poi.apache.org/)上下载POI的开发包。




点击上图中“Download”的连接。




选择合适的下载链接。



点击“Release”。


点击“bin”。



下载上图中的poi-bin-3.2-FINAL-20081019.zip压缩包。

解压后文件结构如下。主要要用到的开发包是poi-3.2-FINAL-20081019.jar,Docs文件夹里是帮助文档。



 
接下来我们再看看如何看帮助文档
 

 
在刚才的解压缩目录的Docs目录下还有一个apidocs目录,点击里面的index.html,就可以
查阅POI应用的帮助文档。


至此POI开发包算是安装好了。
 

2009年9月13日星期日

(转)震撼!从日本回来 不得不对日本社会竖大拇指

        昨天刚刚从日本回来,参加了一个6天行程(2009年8月13日至17日)的旅游团。本来对日本游没有什么兴趣,主要是为了陪老婆去的,但我没有想到这次去日本对我的震撼是那么的大。我不是一个常发贴的人,但这次的心灵震撼让我不得不写出来。
  如果说只是观光,日本的旅游资源绝对比不上我们中国,我想这也是我对日本旅游没有兴趣的原因吧,而且去之前据说很多中国人到日本旅游的目的更多的是为了购物,尤其是女孩,那里的化妆品、名牌确实比国内便宜一些,而且种类齐全。我几乎没有什么准备去的,所以更多的时间留在了对日本社会方方面面的观察上,以至于6天行程对我的内心震撼如此的大。
  首先说说我看到日本的经济情况。
  日本是一个经济非常繁荣的国家,可以说这边都是集团性的经济动物,大型的成功公司比比皆是,无论是东京还是大阪,甚至一些小城市,都能看到整齐而繁华的街道和商店,那种繁华不是一两张照片能感觉到的,你如果在那样密度的繁华区域走很久之后,你会感到惊讶的。尤其是自动贩卖机和便利店,非常之多,寺庙、办公楼、停车场、甚至很偏的一些仓库区以及每一层酒店的楼道里都能很轻松地看到。很少能看到我们比较常见的那种家庭式的“小卖部”,基本上这些自动贩卖机和便利店都是连锁公司的行为。在日本的银行很少看到向中国这样排大队的现象,因为很多缴费业务在这些便利店就可以完成。在商业上,日本的零售业可以说是一个绝对的成功,就像血管一样把商品的销售渠道做到了极致!这样也从另外一方面完全阻挡了外国零售商的进入,2005年,家乐福和沃尔玛均从日本退出就映正了这一点。事实上,零售渠道的建设其实同样具有战略意义,对于控制消费品,推动社会建设有着不可替代的作用。而反思我们现在,家乐福、沃尔玛、华堂、7-11等这些零售商正以最快的速度在我过各地扩张。也许在大城市有些东西感受不深,如果你在一个中小城市,就会发现类似家乐福、沃尔玛这样的大型超市在不断击垮着当地的商场!可以说,日本牢固地守住了自己的这个重要领域。
很常见的自动售货机,属于不同的公司,以饮料居多
另外有必要提一下的是日本的农村,从农村也可以看到日本经济的发达。首先农村的住房和城市的居民住房一样漂亮,都是那种经过设计的小别墅,或者说那种阁楼建筑,便利店、卖车店、饭店和城里基本没有什么差别,而且日本的田间居然能看到大量的路灯,种茶的地方还有那种小风车,用来吹冬天的雪花,避免冻伤茶叶。农村还能看到球场和高档餐饮场所。
  另外在东京、大阪的商业区你会发现他们的商铺密集程度非常之高,店铺虽然大多数都是中小型的,但整体占地面积通常都能走一个小时,而且人流量都很大,这从一个侧面体现出了日本人的购买力。下面这些数字是从网上找的:日本人固定月工资比中国要平均的多,差异幅度有,但是不会特别的大,一般可以简单地计算:大约多少岁每月就可以挣多少万日元。例如30岁拿30万日元,50岁拿50万日元,再加上夏季和年终的两次共2-5个月的奖金。所以30岁年收入一般是450万日元,40岁年收600万日元,以上都是税后收入。人民币对日元可以用100:7来计算,即中国月平均工资/物价=1500元/7元=214件。日本30岁工人的月工资/物价=300000日元/100日元=3000件,日购买力中国214件/30 天=7件/天,日本3000件/30天=100件/天。反过来理解物价/工资比就是中国物价一天工资能买7件,日本一天工资可以买100件。这样的对比太能说明差距了。
东京的涩谷
东京的银座
  再说说日本的环境
  两个字可以概括:干净。这个很大程度上建立在日本的国民素质基础之上。
  空气质量:基本上我到的这几天都是那种清澈的蓝天,一路上我都在找那种冒黑烟的工业区,很遗憾,我虽然路过了很多工业区,但确实没有发现那种冒黑烟的烟囱。也看到了一些烟囱,和我们的不同,我们的烟囱是那种圆柱型,人从外面可以往上爬的那种,而我看到的烟囱都是方柱型,带窗户,一看就是人可以在里面走楼梯上去的那种,而烟囱的顶端有点象一些汽车的排气管形状,基本没有看到冒气的。我猜想烟囱里面的结构应该是有很多功能性的。另外日本满大街都是小型两厢车,也为减排作出了贡献。当然,海洋性气候可能也帮了他们很多忙。
  农村和城市:日本的农村环境保护的非常好,基本没有那种尘土飞扬的地方,要么种田,要么住人,要么就是那种一看都有很久了的密林。那种自然的树林一看就没有经过砍伐过,都是植被非常密集的那种,显然不是人工种植的,据说日本人不砍自己国家的树林,所以你会发现那种长满青苔的大树和密集的野草地特别多。比如我们去富士山的时候,路上全是茂密的树林,里面能看见有很多自然倒下的树木,上面长满了青苔和各种植被,显然已经倒了很多年了,但没有人去搬走,仍然让它保持着最自然的形态。说实话,那样的原始森林,人进入根本无法下脚,所以也没有人跑到里面破坏。日本城市中也经常能看到很多一看就是很老的树和小树林,另外还有很多整齐的草地,是可以践踏的(想到日坛公园,有一对老外在草地上铺东西坐下睡觉,被保安轰走时的表情了,他该多么疑惑呀)。但所有草地的边际都是非常整齐的,也没有我们常见的那种草地上被人踩出来的“人造小路”。由于灰尘少,草地和树木都显的极其干净。
上面那张是普通农村民居
        居民住所和汽车:在日本无论是农村还是城市,最常见的民宅是那种日式,或是有些欧式的小阁楼,有点别墅的意思。一般阁楼前面还会有自家种的竹子、树或者花什么的,据说自家前面绿化是否整洁直接体现除这家人的品味和勤奋程度,一般都是由家庭主妇负责的。这种日式的民宅基本结构都是木头的,我看见一个正在盖的房子,整个框架和屋顶全是木头。这样的民宅有一个好处就是可以自由设计,所以很多房子都设计的很漂亮,可以是欧式的,也有日式的,或者土洋结合的。
  日本很多家庭都有两辆汽车,但大多数汽车都是两厢型的小车。不得不说的还是干净的问题,路面上你绝对看不到沾上泥土,或者旧的掉漆的汽车,每辆车都跟新车一样,包括大客车和卡车,基本上所有车的轮胎和轮毂都是新的一样,这点我觉得比较惊讶,很多大车的轮毂上的螺丝都是闪亮的。环境好是一方面,但下雨什么的难道不会锈的吗?我的车是换了不锈钢的轮毂,但日本车难道都是不锈钢的轮毂吗?
  吸烟问题:在日本边走边抽烟是禁止的,虽然也没有人管,但是确实没有人边走路边抽烟,哪怕是街头混混。街道一般都有专门的吸烟点,那种上面带网格的垃圾筒,里面会有水。在东京还看见那种烟草商提供的免费吸烟点,可以坐在空调房里抽烟,而且还提供一些小服务,比如喝水、充电什么的。另外,街头还有一种象小门脸一样的吸烟点,上面写着“20岁以上进入”,“有权查看身份证”,旁边就是提供这个小门脸的烟草商的店,我以为那个查身份证不会有人那么认真,更何况查的人是卖烟的,多卖点才好呢。谁想我真的碰到一个人被烟草店的人查,面向很小的痞子样,不过看完身份证,确实满了20岁。
  开始我觉得挺奇怪,干脆不允许在公共场合抽烟不就行了,为什么仅仅不能走路吸烟?后来在一个吸烟点看到了带图示的解释有点啼笑皆非,理由有叁:1、吸烟时大人手的位置和小孩头的位置相当,容易碰到小孩(这点勉强算个理由)2、烟蒂容易堵塞下水道;3、香烟烟蒂容易烫到小猫小狗和蚂蚁等动物(这点太强了!)
  日本女人抽烟的很多,很多地方能看到家庭主妇带着孩子在吸烟点抽烟的。
  另外,日本的饭馆只要没有贴着禁烟的标示,就可以抽烟,习惯了在北京的饭馆不能抽烟后,到日本还有点不习惯,日本人不忌讳在饭馆抽烟影响其它人,但烟灰缸你要主动要,桌子上不会专门摆着一个烟灰缸。

  卫生间:日本的公共卫生间都是免费的,无论地铁里的还是街道上的,或者农村的,干净程度都能媲美首都机场的卫生间,都是带冲洗烘干装置的那种马桶,女士的还有“音姬”,就是坐在上面会发出流水声,掩盖不雅声的装置。每个卫生间都有放卫生纸的装置,但不是所有卫生间都有卫生纸的,比如靖国神社里的卫生间就没有。

  垃圾:日本已经完全实现了垃圾分类,这点挺可怕,这样他们的垃圾有效利用率会提高很多,除了节省资源外,还额外创造财富。垃圾分类分为纸类垃圾、塑料瓶、易拉罐和其他,专门看了很多垃圾桶,确实没有乱扔的。他们的意识怎么能如此的统一?

  水:去之前听说日本的自来水都是可以喝的,但到了以后才发现不是这样的,有些是的,但也有不能喝的,很多街头、公园、地铁等公共场所都会提供那种可以喝水的龙头。大多数酒店的自来水也是可以喝的,但最好看到相关标示再喝。除了自来水外值得一提的是他们的自然水资源。在飞机快降落的时候(大阪机场是在海上填出来的),看到大面积的海岸,没有那种白色泡沫,水都非常清澈,你会发现日本的河流也是如此,就连居民区的小溪流都是清澈见底的那种,很难见到漂流物,更没有恶臭。我在南方呆过很多年,看似简单的一个现象,但背后制度、科技、投入、执行力和自觉力的支撑很强大呀!

  再谈谈日本的交通。
  日本出行包括几种手段:自驾车、地铁、出租车和自行车,摩托车也有,但绝没有那么密集,都是男的骑的那种比较彪悍的摩托。

  先说说这次去日本坐的比较多的地铁,他们也叫“电车”。这可以说是日本最常用的交通工具了。如果你看到东京的地铁图的话,你会晕的,跟蜘蛛网一样。大多树地铁的地面口都很小,有的就像一个卖烟的小铺那么大点,但如果下到地下的话,你会发现别有洞天。日本的地铁由于建设的很早,现在看来都比较旧,但都很干净,而且有女士专用车厢(但好像不起作用,男的一样大摇大摆的进)。买地铁票是选择钱数不是选择去哪站,一般地铁票从160到500(人民币11元到35 元)按远近不等。日本人在地铁里面看书和玩手机的居多,很少有说话的,所以地铁里非常沉默,而且给老人让座不是普遍习惯。和我们不一样的是他们上下车都非常谦让,没有人抢座位。

  日本的公路和高速路都比较窄,大多数高速都是单向2车道的。日本车也非常多,但都特别的规矩和默契。他们可以闯黄灯,但是决不闯红灯,尤其是人行道最能体现车与人的默契,无论是行人还是司机,绝对遵守红绿灯指示(一个只有三四步远的人行道,明显两边都没有车,可是没有人过,因为是红灯),没有红绿灯的人行道,车辆会主动让人。这样做的好处是大街上的车开的都非常快,在日本,行人没有走人行道被撞,司机不负责。路上很难见到抢道和加塞的车,车和车之间都异常谦让,当并道时,都遵循一走一让的原则。在高速路上,我们遇到了堵车,我们的大车始终和前车保持着三四个车位的距离,旁边一条道的车虽然也堵在路上,但是没有车到我们前面加塞。大家显的异常友好。让我想起在国内有个周末去十渡的路上,一条双向两车道的路愣被抢成了单行四车道,连两边的应急车道都挤满了加塞的车,结果两边谁也别走,40多分钟的路,我开了5个小时!而且每天上班的路上我都恨不得给自己的车上装上铠甲,去冲撞那些自私的加塞车。

  日本的出租车很有特点,司机都是老人,那种头发都花白的,还有留长胡须的。车基本上都是老式的丰田皇冠那种,但很新很干净。这些司机都非常地有礼貌,穿着虽然不统一,但都是西装革履的,还有人戴领结的。我在路边观察过一个老司机,他会下车站到乘客上车的那边戴好帽子,然后象站岗一样地站在那里等客人,很标准的站姿。没有想到的是他居然姿势不变地站了有20分钟才来了一个客人,他主动地打开车门,用手互着客人的头,等客人坐进去之后跑到车那一边去开车。那天可是大太阳的中午呀,这太让我震撼了。当然不是所有的出租司机都会站在外面等,但基本上你会发现他们的出租司机都是礼仪专家。

  日本的自行车也很普遍,而且大多数自行车都带灯,且车很新,很难看到旧车。
 
可爱的熊猫公车
街头摩托
东京蜘蛛网般的地铁
  接下来说说我感受的日本文化。
  传统文化:个人认为日本文化虽然山寨了我们中国文化,但他们保留和继承的非常好,并且很纯粹。日本的文化继承在今天看来是值得夸耀的。街头巷尾你都能看见穿着传统和服的日本人,包括很多商家的营业人员,对他们而言是很普通的事情。不光服装,包括很多的建筑、用品、食品等等,你都能找到日本古代的感觉。在这些表象下面,也许还有他们的精神。日本每年很多自杀的人,去年达到了5万人,很多人自杀是因为责任心,比如在公司犯错,或者失误等等,这样自杀的人在整体中不在少数。这个现象虽然极端,但是更普遍的是他们整体内心中的那种可怕的责任感和自尊心。我是作企业高管的,事实上现代企业中最主要的特征是对人的管理,把人管好,让每一个人都发挥出最大效率,企业基本上成功了一半。而日本人的这种民族潜意识是把每一个人都变成了负责任的工具,这样的企业效率和竞争力会是惊人的!另一方面,这种良好的传统继承也更加加深了他们的凝聚力。只可惜,他们忘了他们的祖先是中国呀!!
  除了传统文化外,日本的现代文化也十分的发达。什么漫画、电视剧、音乐这些我就不说了。我说说我看到的一些现象吧:在日本,你会发现所有的店面、商品等等人造物都特别的精致,除了制作精细外,还有一个就是他们都经过精心的设计。就拿各种小点心来说,每种点心别管好不好吃,光包装你就会觉得想要一个,非常精美。还有就是他们的商业店面,都设计的非常有特点,很难见到有那种喷绘布一贴就是个店面的。这个现象从一个侧面说明日本人普遍审美水平,社会已经不容那种没有审美的东西了。此外,在大城市里看见书店我觉得不新鲜,但在农村看到一个装修精美的大书店就比较奇怪了吧,我想精明的日本人是不会在一个没人看书的地方开书店的!书店里面绝不只是漫画和杂志呀,那些是少数!
  当然日本的色情文化也很发达,成人杂志一般便利店和书店都能买到,还有DVD什么的,还有很多色情器械、服装、手办等等,这些也是日本文化的一部分。
 
代代木公园里练剑道的人
日本的色情服饰屋
  说说我接触到的日本人吧。

  总体而言日本人面上都非常客气,很多帖子都提到在日本问路。我在日本也向很多日本人问路求助,那种客气让你觉得很过分。在地铁里一个年轻人为了给我们指路,专门下车,带我们到另一个站口,再跑回去。警察也是那种微笑服务。听到日本话想踢他们的感觉顿然消失。日本的服务员都很有礼貌,如果你买东西的话,一定不要自己拿着,他们会帮你拿着,包装好,再付钱。但日本人的英语水平普遍不高,会说的我觉得也挺难听懂的。比较讨厌的是他们明知道你是外国人还叽里呱啦的日语比划,哪怕是飞机里的空姐。

  另外,日本人好像确实对政治不感兴趣,在涩谷时,突然看到一个竞选党派(居然写着“幸福实现党”)白色的宣传车放着大喇叭,里面的人好像是我在他们到处都贴着的竞选海报上贴着的一个女的,拼命地向大街上的人招手示意,不过好像没有什么人理他,连驻足观看的人都很少。

  再说说臭名昭著的靖国神社吧。

  我去的时候是8月16日,他们所谓的“大祭”是8月15日,那天我看到很多的地方膏药旗降半旗。我是中午10点多到的,人并不多,稀稀拉拉的,门口有卖日本古董的小市场,很多二战期间的东西,看到一本海军舰船当年的日志并配有图片,还是比较动心的,合人民币300多块,但看到摊主穿二战军服的鸟样,没有了心情。还有当年8月15日日本投降那天的报纸。靖国神社总体不大,也就是个小公园那么大点,随意进出,但参拜的地方不能拍照,我照了几张,马上有警察过来阻止。后来我才知道不是靖国神社这样,日本所有的神社、庙宇参拜的地方都是不能照相的。这种神社基本全是用木头造的,估计很容易点燃。神社门前那条路上有很多的树,树上面都会有一个牌子,写着一些二战日本战犯部队的番号,好像他们每个战犯部队后来都成立了纪念会之类的组织。靖国神社里面还有三个给犯了罪的战争动物立的碑,信鸽碑、军犬碑和战马碑,这么看来,靖国神社基本是一个纪念畜牲的地方。在里面转了一圈,没有看到狰狞的右翼分子,只有一个可能是二战老兵的老头在休息区里孤独地吹着口琴,吹了很久,没有人理他,然后一拐一拐地走了,祝他早点收拾收拾去世吧。 
臭名昭著的靖国神社
  最后我需要表明一下我此行最终的立场。
  去日本之前,我对这个国家非常地排斥,而且充满着警惕。但此行让我的内心很难平静,作为一个敌国,一个不肯承认罪行的罪恶国家,我们对他的了解太少了。从各个方面看,日本超出我们太多了,这样的事实是无法回避的。我们太需要去了解这个国家,并学习他的东西了。下飞机后,在首都机场,国航的服务厅里,这边接待着客人,那边肆无忌惮地几个服务人员大声说着明天早上凑钱卖煎饼的事情。打车,一上车刚说出自己要去的地方,司机就面目狰狞地嚷嚷“到20 公里了吗?”,既不情愿地开着车,打着手机(他们不到20公里的话,可以回来不用排长队拉活),一路上不断有人抢道,然后他也抢,在自行车道上不断杀出向前蹭的车。看到这些,回到祖国的美好心情顿时跟吃了个苍蝇似的不是滋味。国民素质的差距让我很难骄傲起来。在敌国,我不自觉地成为了一个有礼貌,谦和的人,因为他们的国民对所有人都是那样的,可在我们自己的家园里,我们的国民已经忘了自己的根,都在尽力表露着自己的自私和彪悍,我用不了多久就要去习惯和同胞斗智斗勇。可悲呀!
  昨天晚上看电视,无意间看到一个国学大师的培训课,不禁感悟,我们失去的太多了。要知道,日本的礼仪和文明是从中国传过去的,而现在的我们,别说内在的东西了,就连基本的形式也消失殆尽了!“知己知彼,百战不殆;不知彼而知己,一胜一负;不知彼,不知己,每战必殆”,我突然发现,我们居然在不知不觉中进入到了“不知彼,不知己”的状态当中。我们到底是中国人还是“糟蹋中国的人呀”?

  写这么长一个东西的最终目的不是抱怨,也不是艳羡,而是希望借助日本一行的感受和所见所闻给我深爱的祖国的同胞们一个警醒!与敌国相比,我们缺的不是物质,而是心!我们需要集体性地“补心”了呀!

  我们古老的祖先们用自己的智慧创造了具有“大乘气象”的中国文化——国学,这是我们老祖宗留下的最宝贵的东西,从齐家到治国,从礼仪到兵法,这些宝贵的东西我们应该捡起来了,是到了国民精神复兴的时候了!现在的战争是隐形的战争,是经济之间的战争,用得不是彪悍和蛮力,用的是高素质的人的智慧及知识,这样的人组成的经济体才是最锐利的现代武器。强烈建议大家有机会一定好好学学老祖宗的东西,让自己让身边每一个人都进步起来。每天自省一下,我的工作做好了吗?我今天违法或违规了吗(乱闯红灯就是违法,乘扶梯不站右边就是违规)?我伤害别人了吗?我学习了吗?……只有我们每一个人自强不息,中华民族才能生生不息!!

  祈愿吾堂堂中华早日复兴!!

  最后,奉劝那些在论坛中找各种机会骂人的网友,有那个时间,有那个脑子多说点对别人有用的话,少干点破坏感情的事!      

初来日本

        来日本算来也有三年多了,刚来的那一天,还是相当兴奋的。今天就来简单回忆一下那天的出国流程以及到日本第一天的印象。
        那一天,2006.7.20,是女朋友(现在的老婆)送我去的机场。第一次做飞机,第一次出国,也是第一次来到上海浦东国际机场。
       上海浦东国际机场离市区有一个多小时的车程,打的要150元左右吧,方便是方便,但感觉太贵了,所以搭机场线巴士是个很好的选择。总共有8条线,我坐的是5号线,在火车站南广场边上,挺好找。
       来到机场,进入大厅,当然要到国际出发厅,而不是国内。先要去登录口CHECK IN和拖运行李。机场大厅很大,登录口很多,都用大写英文字母标识。首先要找你要乘坐的航班所在的登录口,有电子屏幕可查,如果实在不知道怎么查,那只好找人问一下了。
       找到登录口,把护照和机票给办理人员,再将要托运的行李搬到旁边的传送带上,称称看有没有超重。我那时候第一次出国,女朋友帮我买了很多东西,已经超出30公斤了,好在卖我机票的人帮我打过招呼了,否则可是要罚很多钱的,国内多少不知道,日本这边的机场大概要一万日元左右。办完手续后,工作人员会给你一张登机票,这样就算完成CHECK IN了,如果时间多的话,你可以随便在大厅里逛逛。
       接下来就是安检了,这时候送机的人就不能再送了,而且还需要提供护照和登机票给工作人员检查。忙的时候要排很长的队伍,所以建议在起飞前至少1小时进行。首先是出境手续,工作人员会在你护照上盖个章,然后再进行安检(基本上和搜身差不多)。安检的地方,将随身带的行李,放到传送带上,通过安检,并把身上有的金属物品如手机,硬币等,全部放到一个小篓子里,通过安检。
       过了安检以后,根据登机票上的候机厅号(日本語:搭乗口),找到相应的候机厅,去那里候机。登机一般在起飞前15分钟开始进行,先是商务舱和抱小孩的妇女们等优先登机,接下来才轮到经济舱。登机前如有时间,你可以逛逛里面的免税商店。国内机场的免税商店,我个人觉得不逛也罢,东西一点不便宜,还很贵,纯粹是为了赚老外的钱。日本的机场免税店就不错,确实要比外面便宜很多,东西也好。我经常看到国人从日本回国的时候,化妆品和电子产品,都是几大包几大包的买,真是叹为观止。
        上了飞机以后,要关掉手机之类的电子产品的电源。起飞前,要系好安全带。我坐过的航班有美西北的,中国东方的,全日空ANA的,还有日本航空JAL的,感觉下来,JAL的比较舒服。
        飞机起飞后10分钟就平稳了,这时候空姐们就开始准备餐饮了。套餐量不太多,但也算比较丰富,而且一般都包含一个甜点。饮料品种也不少,有果汁,可乐,啤酒,红酒,喝完了还可以再要。听说有日本人在飞机上喝酒喝到醉的。
        每个座位的前方都有一个小屏幕,你可以看电影,也可以玩游戏什么的。由于从上海到日本实际费时2个半小时,所以想看完一整部电影还不太容易。
        从上海到日本一般都是到成田机场,因为有时差,记得到日本之后要把表往前拨快一小时,如果要别人接机,也不要搞错中国时间和日本时间。
        下了飞机首先要做的是边检。这时候你算是真正感觉到已经来到了日本国土了。边检在三楼,初次入国的话,要填一张出入境登记卡(签证有效期内回国探亲再入境的不用,简称再入国),有左右两联,主要填写姓名,护照号码,航班号,在日居住地等。填好后就去排队,排队也要注意排在哪里,因为初次入国和再入国不在一个地方,最简单的方法就是找人最多的地方排,如实在不放心,可以问工作人员,当然要用到日语了。日语不好也不要紧,他会指给你看。
        排了很长的队伍,终于轮到你了,递上护照和刚才填的出入境卡,边检官可能会问一些问题,如第几次来啊,来干嘛之类的。从2007年开始,日本机场边检时,要按电子指纹和拍照。边检会提示你让你伸出两手食指,按在前面的一个小机器上,然后再对着摄像头拍个照。没问题的话,边检官会把出入境卡的右边(入境卡)撕下,左边(出境卡,回国要用)钉在护照上,再在护照上盖个章。
        过了边检下一层楼去拿行李(二楼),看看电子屏幕找你的航班号,确认应该在哪个口拿。东西多的话,可以找个推车。这时还有最后一张表要填,叫携带物品申报卡,大厅里有的拿,也有样板参照。首先要填你的基本信息,和刚才出入境卡差不多,接下来就是有没有带多少多少以上的现金,有没有禁止入境的物品,烟酒有没有,有多少,等等。统统填没有就行。接下来就是最后一关了,行李检查。把护照和刚才填的申报卡交给工作人员,工作人员有时会问你一些问题,大致就是来干嘛啊,行李就这些吗,也有过于认真的工作人员会要求你打开行李让他看一下。不过基本上没啥大问题。
         这样总算出关了,接下来就要根据你的目的地,选择交通方式了。打的最方便,也是最贵的,基本上要2万左右(算算人民币是多少吧),远的还不止。其次是巴士,不过刚来,应该还不懂怎么坐巴士,反正我到现在为止没在日本机场坐过巴士。日本的轨道交通相当发达,机场有两条轨道线,一条JR线,一条京成线,看你去哪里。如有人接机,那没问题,没有的话,那就一定要事先调查一下了,包括怎么买票,应该坐哪条线,坐到哪一站下,中途要不要转车等等。
         最后再补充说两点,坐手扶电梯时要靠左站,右边是应急通道。等车时要排队,车到了要先让里面的人下车,然后再依次上车,别还跟国内一样,没等人家下车呢,就一拥而上往里挤。国内的一些恶习,你会发现,来日本后,你会慢慢改掉的,这是我来日本的一点体会。
        如果还有什么问题,欢迎在我的博客给我留言,或发邮件给我。最后祝大家都能有一个愉快的日本之行。