java 文件

来源:互联网 发布:冒险与挖矿 源码 编辑:程序博客网 时间:2024/05/11 16:40

java 文件操作

关键字: java
java 文件操作
1。新建目录

<%@ page contentType="text/html;charset=gb2312"%>
<%
String filePath="c:/aaa/";
filePath=filePath.toString();//中文转换
java.io.File myFilePath=new java.io.File(filePath);
if(!myFilePath.exists())
myFilePath.mkdir();
%>

2。新建文件

<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="java.io.*" %>
<%
String filePath="c:/哈哈.txt";
filePath=filePath.toString();
File myFilePath=new File(filePath);
if(!myFilePath.exists())
myFilePath.createNewFile();
FileWriter resultFile=new FileWriter(myFilePath);
PrintWriter myFile=new PrintWriter(resultFile);
String strContent = "中文测试".toString();
myFile.println(strContent);
resultFile.close();
%>

3。删除文件

<%@ page contentType="text/html;charset=gb2312"%>
<%
String filePath="c:/支出证明单.xls";
filePath=filePath.toString();
java.io.File myDelFile=new java.io.File(filePath);
myDelFile.delete();
%>

4。文件拷贝

<%@ page contentType="text/html; charset=gb2312" %>
<%@ page import="java.io.*" %>
<%
int bytesum=0;
int byteread=0;
file://读到流中
InputStream inStream=new FileInputStream("c:/aaa.doc");
FileOutputStream fs=new FileOutputStream( "d:/aaa.doc");byte[] buffer =new byte[1444];
int length;
while ((byteread=inStream.read(buffer))!=-1)
{
out.println("<DT><B>"+byteread+"</B></DT>");
bytesum+=byteread;
System.out.println(bytesum);
fs.write(buffer,0,byteread);
}
inStream.close();
%>

5。整个文件夹拷贝

<%@ page contentType="text/html;charset=gb2312"%>
<%@ page import="java.io.*" %>
<%String url1="C:/aaa";
String url2="d:/java/";
(new File(url2)).mkdirs();
File[] file=(new File(url1)).listFiles();
for(int i=0;i<file.length;i++){
if(file[i].isFile()){
file[i].toString();
FileInputStream input=new FileInputStream(file[i]);
FileOutputStream output=new FileOutputStream(url2+"/"+(file[i].getName()).toString());
byte[] b=new byte[1024*5];
int len;
while((len=input.read(b))!=-1){
output.write(b,0,len);
}
output.flush();
output.close();
input.close();
}
}
%>

6。文件下载

<%@ page contentType="text/html; charset=gb2312" %>
<%@ page import="java.io.*" %>
<%
String fileName = "zsc104.swf".toString();
//读到流中
InputStream inStream=new FileInputStream("c:/zsc104.swf");
//设置输出的格式
response.reset();
response.setContentType("bin");
response.addHeader("Content-Disposition","attachment; filename=/"" + fileName + "/"");
//循环取出流中的数据
byte[] b = new byte[100];
int len;
while((len=inStream.read(b)) >0)
response.getOutputStream().write(b,0,len);
inStream.close();
%>

7。数据库字段中的文件下载

<%@ page contentType="text/html; charset=gb2312" %>
<%@ page import="java.sql.*"%>
<%@ page import="java.lang.*" %>
<%@ page import="java.io.*" %>
<%@ page import="com.jspsmart.upload.*" %>
<%@ page import="DBstep.iDBManager2000.*"%>
<%
int bytesum=0;
int byteread=0;
//打开数据库
ResultSet result=null;
String Sql=null;
PreparedStatement prestmt=null;
DBstep.iDBManager2000 DbaObj=new DBstep.iDBManager2000();
DbaObj.OpenConnection();
//取得数据库中的数据
Sql="select * from t_local_zhongzhuan ";
result=DbaObj.ExecuteQuery(Sql);
result.next();

file://将数据库中的数据读到流中
InputStream inStream=result.getBinaryStream("content");
FileOutputStream fs=new FileOutputStream( "c:/dffdsafd.doc");

byte[] buffer =new byte[1444];
int length;
while ((byteread=inStream.read(buffer))!=-1)
{
out.println("<DT><B>"+byteread+"</B></DT>");
bytesum+=byteread;
System.out.println(bytesum);
fs.write(buffer,0,byteread);
}
%>

8。把网页保存成文件

<%@ page import="java.text.*"%>
<%@ page import="java.util.*"%>
<%@ page import="java.io.*"%>
<%@ page import="java.net.*"%>
<%
URL stdURL = null;
BufferedReader stdIn = null;
PrintWriter stdOut = null;
try {
stdURL = new URL("http://www.163.com");
}
catch (MalformedURLException e) {
throw e;
}

try {
stdIn = new BufferedReader(new InputStreamReader(stdURL.openStream()));
stdOut = new PrintWriter(new BufferedWriter(new FileWriter("c:/163.html")));
}
catch (IOException e) {
}

/***把URL指定的页面以流的形式读出,写成指定的文件***/
try {
String strHtml = "";
while((strHtml = stdIn.readLine())!=null) {
stdOut.println(strHtml);
}
}
catch (IOException e) {
throw e;
}
finally {
try {
if(stdIn != null)
stdIn.close();
if(stdOut != null)
stdOut.close();
}
catch (Exception e) {
System.out.println(e);
}
}
%>

9。直接下载网上的文件

<%@ page import="java.io.*"%>
<%@ page import="java.net.*"%>
<%
int bytesum=0;
int byteread=0;

URL url = new URL("http://pimg.163.com/sms/micheal/logo.gif");
URLConnection conn = url.openConnection();
InputStream inStream = conn.getInputStream();
FileOutputStream fs=new FileOutputStream( "c:/abc.gif");

byte[] buffer =new byte[1444];
int length;
while ((byteread=inStream.read(buffer))!=-1)
{
out.println("<DT><B>"+byteread+"</B></DT>");
bytesum+=byteread;
System.out.println(bytesum);
fs.write(buffer,0,byteread);
}
%>

10。按行读文件
<%@ page contentType="text/html; charset=gb2312" %>
<%@ page import="java.io.*" %>
<%
FileReader myFileReader=new FileReader("c:/哈哈.txt");
BufferedReader myBufferedReader=new BufferedReader(myFileReader);
String myString=null;
String resultString=new String();
while((myString=myBufferedReader.readLine())!=null)
{ resultString=resultString+myString+"<br>";
}
out.println(resultString);
myFileReader.close();
%>

11。 数据库里字段文件直接下载到客户端
<%@ page import="java.sql.*"%>
<%@ page import="java.lang.*" %>
<%@ page import="java.io.*" %>
<%@ page import="com.jspsmart.upload.*" %>
<%@ page import="DBstep.iDBManager2000.*"%>
<%
String fileName = "bb.doc".toString();
//打开数据库
ResultSet result=null;
String Sql=null;
PreparedStatement prestmt=null;
DBstep.iDBManager2000 DbaObj=new DBstep.iDBManager2000();
DbaObj.OpenConnection();
//取得数据库中的数据
Sql="select * from marklist order by markdate desc";
result=DbaObj.ExecuteQuery(Sql);
result.next();
//将数据库中的数据读到流中
InputStream in =result.getBinaryStream("markbody");
//设置输出的格式
response.reset();
response.setContentType("application/Msword");
response.addHeader("Content-Disposition","attachment; filename=/"" + fileName + "/"");
//循环取出流中的数据
byte[] b = new byte[1024];
int len;
while((len=in.read(b)) >0)
response.getOutputStream().write(b,0,len);
in.close();
%>


12。文件夹遍历
<%@ page contentType="text/html; charset=gb2312" %>
<%@ page import="java.io.*" %>
<%
String url1="C:/aaa";
File f=(new File(url1));
if(f.isDirectory()){
File [] fe = f.listFiles();
go_on:
for (int i = 0;i<fe.length;i++){
if (fe[i].isDirectory()){
File [] fe1 = fe[i].listFiles();
for (int j = 0;j<fe1.length;j++){
if (fe1[j].isDirectory())
continue go_on;
out.println(fe1[j].toString());
}
}
else out.println(fe[i].toString());
}
}

%>
13。通过字符编码移动文件
<%@ page contentType="text/html; charset=gb2312" %>
<%@ page import="java.io.*" %>
<%
String ret=new String();
try
{
byte[] bytes=new byte[102400];
InputStream in=new FileInputStream("c:/aaa.doc");
in.read(bytes);
ret=new sun.misc.BASE64Encoder().encode(bytes); //具体的编码方法
in.close();
}
catch(FileNotFoundException e)
{
e.printStackTrace();
}
catch(java.io.IOException ex)
{
ex.printStackTrace();
}
out.println(ret);

byte[] bytes = new sun.misc.BASE64Decoder().decodeBuffer(ret);
java.io.ByteArrayInputStream inStream=new java.io.ByteArrayInputStream(bytes);
byte[] buffer =new byte[1444];
FileOutputStream fs=new FileOutputStream( "d:/aaa.doc");
int bytesum=0;
int byteread=0;
while ((byteread=inStream.read(buffer))!=-1)
{
bytesum+=byteread;
fs.write(buffer,0,byteread);
}
%>
14。把文件编码成base64字符串
<%
String ret=new String();
byte[] bytes=new byte[1024];
String aa="aaaa";
bytes=aa.getBytes();
ret=new sun.misc.BASE64Encoder().encode(bytes); //具体的编码方法
bytes = new sun.misc.BASE64Decoder().decodeBuffer(ret);
aa=new String(bytes);
out.println(aa);
%>


12。文件夹遍历
<%@ page contentType="text/html; charset=gb2312" %>
<%@ page import="java.io.*" %>
<%
String url1="C:/aaa";
File f=(new File(url1));
if(f.isDirectory()){
File [] fe = f.listFiles();
go_on:
for (int i = 0;i<fe.length;i++){
if (fe[i].isDirectory()){
File [] fe1 = fe[i].listFiles();
for (int j = 0;j<fe1.length;j++){
if (fe1[j].isDirectory())
continue go_on;
out.println(fe1[j].toString());
}
}
else out.println(fe[i].toString());
}
}

%>
13。通过字符编码移动文件
<%@ page contentType="text/html; charset=gb2312" %>
<%@ page import="java.io.*" %>
<%
String ret=new String();
try
{
byte[] bytes=new byte[102400];
InputStream in=new FileInputStream("c:/aaa.doc");
in.read(bytes);
ret=new sun.misc.BASE64Encoder().encode(bytes); //具体的编码方法
in.close();
}
catch(FileNotFoundException e)
{
e.printStackTrace();
}
catch(java.io.IOException ex)
{
ex.printStackTrace();
}
out.println(ret);

byte[] bytes = new sun.misc.BASE64Decoder().decodeBuffer(ret);
java.io.ByteArrayInputStream inStream=new java.io.ByteArrayInputStream(bytes);
byte[] buffer =new byte[1444];
FileOutputStream fs=new FileOutputStream( "d:/aaa.doc");
int bytesum=0;
int byteread=0;
while ((byteread=inStream.read(buffer))!=-1)
{
bytesum+=byteread;
fs.write(buffer,0,byteread);
}
%>
14。把文件编码成base64字符串
<%
String ret=new String();
byte[] bytes=new byte[1024];
String aa="aaaa";
bytes=aa.getBytes();
ret=new sun.misc.BASE64Encoder().encode(bytes); //具体的编码方法
bytes = new sun.misc.BASE64Decoder().decodeBuffer(ret);
aa=new String(bytes);
out.println(aa);
%>
众所周知,Windows的可执行文件可以划分为两种形式:程序和动态链接库(DLL)。而在什么时候需要使用动态链接库呢,动态链接库又有一些什么样的好处呢:
1、一个DLL可以提供给不同的程序使用,而这个DLL只需要在内存中加载一次,这样就节省了系统的内存。
2、我们可以提供DLL的不同版本来更新我们的程序,而不需要重新编译我们的程序。
3、使用了DLL组件包可以大大减小可执行文件的规模。
4、如果应用程序是基于同一个组件包,我们将接生许多内存和代码分配。
从上面看来,DLL是独立于编程语言的;在Windows编程环境下,我们可以在不同的编程语言中调用相互编写的动态链接库,从而满足不同的需要,并且大大的提高了更新效率。
下面我就讲讲使用在Delphi 5.0中如何编写调用动态链接库的应用程序。

首先,我们要创建一个DLL,在Delphi的菜单中选择File->New,选中DLL,然后点击OK。

这时可以出现编写环境,请注意那里的英文说明,大概讲述了编写DLL时需要注意的地方,其中有一个非常重要的就是尽量避免使用string类型而采用pchar或者shortstring类型,否则传递的参数将出现乱码。
然后,将第一行的Library Project1;改成Lirbrary MyDLL;,同时保存文件,并编译,这就产生了一个DLL;当然这个DLL现在还什么都没有。现在我们给他加上一些功能。

uses
SysUtils,Windows,Registry,Regstr;

Function ChkBoolean():Boolean;stdcall;
Begin
Result:True;
End;

procedure WriteReg(UserName:pchar);stdcall;
var
Reg: TRegistry;
begin
Reg:=TRegistry.Create;
errFind:=False;
try
Reg.RootKey:=HKEY_LOCAL_MACHINE;
If Reg.OpenKey(''SOFTWARE/MyDLL/''+UserName,True) then
Reg.WriteString(''Name'',UserName);
finally
Reg.CloseKey;
Reg.Free;
end;
end;

输入以上的代码,分别是一个函数和一个过程,第一个函数ChkBoolean返回一个真;过程WriteReg读取一个参数并将该参数写入注册表。在程序的最后必须加上一句:
Exports ChkBoolean,WriteReg;
这样表示向外声明可提供给应用程序的函数或过程,也只有在这里声明的函数或过程可以给其他应用程序所调用。
最后,我们编译整个程序,将产生一个MyDll.dll的文件。

现在,让我们创建一个应用程序来调用这个DLL。
点击File->New Application,保存这个工程,记住要和刚才那个DLL工程在同一个目录。
在 implementation 下编写如下代码:
type
TMyProcedure=procedure(UseNam:pchar);stdcall;
function ChkBoolean():Boolean; external MyDLL.DLL'';
第一行定义了一个过程类型,下面会看到这有什么用;
在我们程序的Form上放置一个TEdit和TButton控件,使其如下图所示:

双击按钮,编写onClick事件,代码如下:

procedure TForm1.Button1Click(Sender: TObject);
var
HInst:Thandle;
FPointer:TFarProc;
MyProc:TMyProcedure;
Begin
If ChkBoolean Then
//直接返回函数值,为真,继续运行……
Begin
HInst:=LoadLibrary(''MyDLL.DLL'');
if HInst>0 then
try
FPointer:=GetProcAddress(Hinst,Pchar(''WriteReg''));
//GetProcAddress API函数用于找到DLL中的函数名,并返回一个指针
if FPointer<>nil then
begin
MyProc:=TMyProcedure(FPointer);
//将该函数指针转换成相应的数据类型并调用它
Try
MyProc(Edit1.Text);
except on E:Exception do
ShowMessage(E.Message);
end;
end
else
ShowMessage(''DLL procedure not found!'');
finally
FreeLibrary(HInst);
end
else
ShowMessage(''Library not found!'');
End;
end;

编写完以上代码,马上运行应用程序。在输入框处输入任意字符,并点击按钮,再打开你的注册表,需要HKEY_LOCAL_MACHINE/ SOFTWARE,看看多了些什么。
很有意思吧,呵呵!通过这样一个简单的例子,你可以更加好的运用DLL的强大优势。同时,用DELPHI编写的DLL还可以提供给其他语言环境调用啊,比如VB,VC等等。还不赶快试试?
Java调用动态库最简便方法和最好用的组件
记得以前 Java 要调用C/C++写得动态库都是用的 JNI 方式,还需要自己写不少 C/C++ 代码。比如说要在Java中调用已有的动态库,如 Windows 的 user32.dll 的方法 MessageBoxA,具体步骤是 Java 中声明一个 native 方法,然后用 javah 命令生成JNI样式的头文件,再自己实现头文件中声明的方法,在实现方法中装载动态库 user32.dll,调用 MessageBoxA 方法,需要把自己写的这部分 C/C++ 代码封装成一个动态库,如Sample.dll,最后在 java 中装载 Sample.dll,然后执行其中所声明的本地方法。

可见,用老实的JNI方式,我们在调用一个已知动态库的时候还需要额外生成一个符合JNI规则的动态库作为桥梁,显得有点多余了。

下面我将引入一个开源的组件 JNative,在 http://sourceforge.net/projects/jnative 下载(我是通过在sourceforge中输入java dll搜索到的),通过它调用已有动态库中的方法就非常的方便,因为中间的JNI处理过程它都为我们做好了。JNative 现在还是 Beta1 版,期待正式版的出炉,还不知道这个版本将会有什么Bug出现。

我们下载到的 jnative 的目录中可以看到三个文件,分别是 JNative.dll,libjnative.so,JNative.jar

JNative.dll 为 Windows 平台下用的,可以拷到相应的lib加载路径,如user.dir、path、system32或windows目录下
libnative.so 为Linux平台下用的,可以拷到相应的lib加载路径,如user.dir、path目录下
JNative.jar 这个就是我们编程时候要用的

在下载的 jnative 的源代码中有示例代码,观看代码 org/xvolks/test/JNativeTester.java 就知道 jnative 是如何调用动态库方法的

如代码行 User32.messageBox(0, "Demonstrates JNative in action with many Win32 calls", "Welcome to JNative", 0);

是调用的关User32的messageBox方法,而messageBox的代码是

public static final int messageBox( int parentHandle, String message,
String caption, int buttons) throws NativeException,
IllegalAccessException {
JNative n = null ;
try {
n = new JNative(DLL_NAME, "MessageBoxA" ); // 常量DLL_NAME的值为User32.dll
// 构造JNative时完成装载User32.dll,并且定位MessageBoxA方法
n.setRetVal(Type.INT); // 指定返回参数的类型
int i = 0 ;
n.setParameter(i++, Type.INT, "" + parentHandle);
n.setParameter(i++, Type.STRING, message);
n.setParameter(i++, Type.STRING, caption);
n.setParameter(i++, Type.INT, "" + buttons); // 指定位置上的参数类型和值
n.invoke(); // 调用方法
return Integer.parseInt(n.getRetVal());
} finally {
if (n != null )
n.dispose(); // 记得释放
}
}

上面的注释是我加上去的。
Type有一种叫做Type.PSTRUCT枚举值,对C/C++中结构的处理都考虑到了,只要用JNative的Pointer类的实例来与结构对应就行了。org/xvolks/test/SNDPTester.java中演示了如何传递C/C++中的结构相对应的Java数据类型,也就是怎么封装成一个JNative的Pointer类型。

还有在JNative中用了JDK1.5的一些特性,如枚举、静态引入等,所以在JDK1.4下是不能用的。

附:JNative 当前版本到了 1.3.2 了




--------------------------------------------------------------------------------
[版权声明]本站内文章,如未标注 [转载],均系原创或翻译之作,本人 Unmi 保留一切权利。本站原创及译作未经本人许可,不得用于商业用途及传统媒体。网络媒体可随意转载,或以此为基础进行演译,但务必以链接形式注明原始出处和作者信息,否则属于侵权行为。另对本站转载他处文章,俱有说明,如有侵权请联系本人,本人将会在第一时间删除侵权文章。及此说明,重之之重。
posted on 2006-05-18 02:09 隔叶黄莺 阅读(746) 评论(15) 编辑 收藏



Feedback
# re: Java调用动态库最简便方法和最好用的组件 2007-11-14 10:31 啥事
有没有如何获得dll传出参数的例子 回复 更多评论



# re: Java调用动态库最简便方法和最好用的组件 2007-11-14 12:37 隔叶黄莺
没有这么聪明,C++也没办法知道,只能按照API约定来调用传参取值,知道一个地址不标识是什么类型的 回复 更多评论



# re: Java调用动态库最简便方法和最好用的组件 2007-11-18 10:09 隔叶黄莺
JNative 的 getRetVal() 方法就是获取dll中函数传出的参数。 回复 更多评论



# re: Java调用动态库最简便方法和最好用的组件 2007-11-22 17:34 啥事
可能是我没有表述清楚,我想知道jnative如何调用dll的出参。
getRetVal()只是调用是否成功的一个返回值。如:
我们有个HNBridge.dll中有getParam(Long pDataHandle,String paramName,REF String paramValue,UINT nMaxValuseLenth) 其中REF String paramValue
是一个返回值,getRetVal()只是校验该函数调用是否成功。
java如何调用REF String paramValue。
这是我的源码
public static final Object[] getparam(long s1,String s2,long s4 ) throws NativeException,IllegalAccessException{
JNative n=null;
try{
n= new JNative("HNBridge.dll", "GetParam");
n.setRetVal(Type.INT);
// n.setMemory(0, "");
//n.set
int i=0;
Pointer s6 = new Pointer(MemoryBlockFactory.createMemoryBlock(1024));
s6.zeroMemory();
s6.setStringAt(0, "ddd");
use=new UserCall("");
// s6.setStringAt(0, "sss");
//pTar=new Pointer(MemoryBlockFactory.createMemoryBlock(36));
n.setParameter(i++, Type.LONG, ""+s1);
n.setParameter(i++, Type.STRING,s2);
// n.setParameter(i++, use.createPointer());
n.setParameter(i++, s6);
n.setParameter(i++, Type.LONG, ""+s4);
n.invoke(); // 调用方法
//System.out.println(n.getParameter(0));
// s3=s6.getAsString();
System.out.println(s6.getAsString()+"fhz");
Object [] mm=new Object[2];
mm[0]=n.getRetVal();
// mm[1]=use.getValueFromPointer();
mm[1]=s6.getAsString();
// mm[1]=s3;
//use.dispose();
return mm;

}

但总是得不到正确值
回复 更多评论



# re: Java调用动态库最简便方法和最好用的组件 2007-11-22 17:40 隔叶黄莺
getRetVal()是实际的返回值 回复 更多评论



# re: Java调用动态库最简便方法和最好用的组件 2007-12-10 17:37 hill
为什么我用自己写的程序老是收到这样的错误
Exception in thread "main" java.lang.IllegalStateException: JNative library not loaded, sorry !
at org.xvolks.jnative.JNative.<init>(JNative.java:337)
at org.xvolks.jnative.JNative.<init>(JNative.java:269)
at test.TestJNI.main(TestJNI.java:30)
即使是用JNativeTester.java也会收到错误:
Exception in thread "main" java.lang.UnsatisfiedLinkError: org.xvolks.jnative.JNative.nLoadLibrary(Ljava/lang/String;Ljava/lang/String;Z)I
at org.xvolks.jnative.JNative.nLoadLibrary(Native Method)
at org.xvolks.jnative.JNative.<init>(JNative.java:348)
at org.xvolks.jnative.JNative.<init>(JNative.java:269)
at org.xvolks.jnative.util.User32.MessageBox(User32.java:396)
at test.JNativeTester.main(JNativeTester.java:312)
回复 更多评论



# re: Java调用动态库最简便方法和最好用的组件 2007-12-10 17:42 hill
用JNativeTester.java去load “user32.dll"会出现上面的错误,但是load自己的dll却是Exception in thread "main" java.lang.UnsatisfiedLinkError: D:/Project/test/src/test/umenable.dll: Can't find dependent libraries
?难道我的dll是不能用的? 回复 更多评论



# re: Java调用动态库最简便方法和最好用的组件 2007-12-10 17:43 隔叶黄莺
把JNative.dll 为 Windows 平台下用的,可以拷到相应的lib加载路径,如user.dir、path、system32或windows目录下,保证你的java程序能加载到这个动态库 回复 更多评论



# 还是有问题 2007-12-11 12:38 hill
谢谢你的解答,现在可以load我的dll了不过问题又来了,我发现看不到dll里面的方法,即使用JNative的getDLLFileExports返回的都是(几个dll都是返回这样的)
DllCanUnloadNow
DllGetClassObject
DllRegisterServer
DllUnregisterServer
我的这些dll好像是基于com的,不多我对这些都不熟悉,咋办? 回复 更多评论



# re: Java调用动态库最简便方法和最好用的组件 2007-12-11 12:48 隔叶黄莺
基于Com的,有些不一样的。Com初始化过程在哪里完成的呢 回复 更多评论



# re: Java调用动态库最简便方法和最好用的组件 2007-12-12 10:50 hill
谢谢你的解答,我发现我这个程序用jacob(Java-Com Bridge)来做就可以了,非常简单,只要new一个ActiveXComponent,就可以调用里面的函数了 回复 更多评论



# re: Java调用动态库最简便方法和最好用的组件 2008-04-30 10:18 cary
我用JNative来调用DLL但是现在遇到问题是类型间的转换,DLL里的类型始终不能被JAVA认出来。那怕我在DLL里这样写:return "hello",java里:
n3.setRetVal(Type.STRING);
System.out.println(n3.getRetVal())
都不能被打印出来,不知道你有遇到过类型方面的问题吗? 回复 更多评论



# re: Java调用动态库最简便方法和最好用的组件 2008-04-30 10:32 隔叶黄莺
没遇到这种问题,请把你能重现问题的完整代码贴出来看看 回复 更多评论



# re: Java调用动态库最简便方法和最好用的组件 2008-04-30 12:51 cary
n3=new JNative("CID_test","CID_GetNum");
n3.setRetVal(Type.STRING);
System.out.println("n3=="+n3.getRetVal());
这是JAVA代码。
c++

extern "C" _declspec(dllexport) string CID_GetNum()
{
char buf[32];
string s;
int i=0;
i=SW_ReceiveCID(0,buf);
if(i!=0)
{
s += buf;
return "hello";
}
return "hello";
}
你看看我这样写有问题吗?
@隔叶黄莺
回复 更多评论



# re: Java调用动态库最简便方法和最好用的组件 2008-04-30 21:06 隔叶黄莺
尽量能的话还是严谨一点吧
_declspec(dllexport) 前面是两个下划线,你少写了一个
你用 string 也该把 string.h 或 string #include 进来
SW_ReceiveCID 不存在的函数


存在两个问题
1. 你的动态库必须返回一个 c-style 字符串,如 char*,用 std 的 string,java 那边不会认成是 String,你可以中间过程用 string,最后返回的字符串要是 c-style 格式。这应该不成问题,你见过许多 windows api 就是用的这种字符串,如 LPSTR 样的

2. 你在 java 代码忘了调用 dll 的相应方法,在取返回值之前必须 n3.invoke() 一下。

重新试试吧,祝你好运
由于项目要求,需要用Java调用windows的dll文件,查了一下,如果用JNI的话是比较麻烦的,在sourceforge.net上搜索了一下“Java dll”,首先出现的是Jnative,于是决定用它,后来也试了些别的,但还是JNative好使,简单总结如下:

Java调用动态库所需要关心的问题:
l 如何装载dll文件,以及如何定位所要使用的方法;

l 数据类型是如何对应的;

l 如何给使用的方法传递参数;

l 如何获取返回的值。

JNative INFO:
Resource URL: http://jnative.sourceforge.net/

Source Code: http://sourceforge.net/projects/jnative

Detailed Review: http://jnative.free.fr

JavaDOC: http://jnative.free.fr/docs/

Version:1.3

一个开源的组件,通过它调用已有动态库中的方法就非常的方便,支持CallBack 。

为什么选择JNative
同类的开源组件相对活跃的还有,JNA ( Java Native Access ), Jawin,Nativecall,etc.但是Jnative 相对更容易使用,它对数据类型的处理做的更好。

l JNA 需要用户对所使用的DLL文件事先进行封装,才能装载。另外需要在一个java接口中描述目标DLL中的函数与结构,从而使JNA自动实现Java接口到native function的映射,较麻烦。

l Nativecall 暂时还不知道如何装载dll文件。

l Jawin 数据类型匹配相当敏感,它采用一种叫做”instruction string”的格式来传递参数,还没有完全理解。

How to:
解压JNative-1.3.2.zip 获得三个文件,分别是:JNativeCpp.dll,libJNativeCpp.so,JNative.jar 。


JNativeCpp.dll Windows下用的,拷到windows / system32目录下;

libJNativeCpp.so Linux下的咚咚;

JNative.jar 这是一个扩展包,将其copy到C:/jdk/jre/lib/ext 下(我的目录结构),系统会自动加载。

结构映射(Structure Mapping)




Type
Length
JNative class

DWORD
4
org.xvolks.jnative.misc.basicStructures.LONG

HWND
4
org.xvolks.jnative.misc.basicStructures.HWND

COLORREF
4
org.xvolks.jnative.misc.basicStructures.LONG

COLORREF*
4
org.xvolks.jnative.pointers.Pointer

LPARAM
4
org.xvolks.jnative.misc.basicStructures.LPARAM

LPCCHOOKPROC
4
org.xvolks.jnative.util.Callback

LPCTSTR
4
org.xvolks.jnative.pointers.Pointer











一些关键的类及方法

Class
作用
一般用到的方法(参数略,参考Doc)

org.xvolks.jnative.Jnative
装载dll文件,定位函数
JNative(),setParameter(),setRetVal(),getRetVal() etc.

org.xvolks.jnative.pointers.Pointer
替代本地函数中的的指针,需要先申请一块内存空间,才能创建
Pointer(),dispose()

org.xvolks.jnative.pointers.memory.MemoryBlockFactory
申请一块内存空间
createMemoryBlock()

org.xvolks.jnative.exceptions.NativeException
抛出装载,定位等方面的异常


org.xvolks.jnative.Type
列举和管理Jnative需要的不同的数据类型




(二)

简单测试,Javadoc 下和官方网上有些例子,下面的是我随便从IC读卡程序中找了个DLL进行的测试:
SCReader.dll 下的SCHelp_HexStringToBytes()函数原型
SCREADER_API WINAPI long SCHelp_HexStringToBytes(

LPCTSTR pSrc,

BYTE* pTar,

int MaxCount

);

注意:dll文件需要放到System32下,否则可能找不到



通过Jnative 用java 来调用代码如下:

package onlyfun.dllcall;
import org.xvolks.jnative.JNative;
import org.xvolks.jnative.exceptions.NativeException;
import org.xvolks.jnative.pointers.Pointer;
import org.xvolks.jnative.pointers.memory.MemoryBlockFactory;
import org.xvolks.jnative.Type;
public class UserCall {
/**
* return 转换成功的字节数
*/
static JNative Something = null;
static Pointer pointer;
public String getSomething(String pSrc, Pointer pTar, int MaxCount) throws NativeException, IllegalAccessException{

try{
if(Something == null){
pTar = new Pointer(MemoryBlockFactory.createMemoryBlock(36));
Something = new JNative("SCReader.DLL", "SCHelp_HexStringToBytes");
// 利用org.xvolks.jnative.JNative 来装载 SCReader.dll,并利用其SCHelp_HexStringToBytes方法
Something.setRetVal(Type.INT);
// 指定返回参数的类型
}
int i=0;
Something.setParameter(i++,pSrc);
Something.setParameter(i++,pTar);
Something.setParameter(i++,MaxCount);
System.out.println("调用的DLL文件名为:"+Something.getDLLName());
System.out.println("调用的方法名为:"+Something.getFunctionName());
//传值
Something.invoke();//调用方法
return Something.getRetVal();
}finally{
if(Something!=null){
Something.dispose();//释放
}
}
}
public Pointer creatPointer() throws NativeException{
pointer = new Pointer(MemoryBlockFactory.createMemoryBlock(36));
pointer.setIntAt(0, 36);
return pointer;
}

public static void main(String[] args) throws NativeException, IllegalAccessException {
UserCall uc = new UserCall();
String result = uc.getSomething("0FFFFF", uc.creatPointer(), 100);
System.err.println("转换成功的字节数为:"+result);
TestCallback.runIt();
}
}
Java不能直接调用由c或者c++写得dll(TF_ID.dll),所以只能采用jni得方法,一步一步生成符合规范得dll文件(假设叫FANGJIAN.dll),在FANGJIAN.dll这个文件里来调用TF_ID.dll。注意一点:两个dll文件不能重名,为什么呢? 因为java后来执行时候,必须把两个dll文件均考到java得class文件同一目录下,或者把TF_ID.dll考到system32下也可以,如果重名得话,首先不能考到一个目录下,再则即使将前一个dll考到system32下,那么后一个dll也会出现调用自身dll得问题,大家可想而知了!!!



下面给出了两个例子:



第一个是用java得jni方法生成了一个dll文件,这个dll文件,直接在其方法函数体内写具体实现得方法,然后将dll文件考到java执行得同一目录下,就可以执行成功了!



第二个也是用java得jni方法生成一个dll文件(FANGJIAN.dll),这个dll文件中再来调用IC卡读写器提供得dll文件(TF_ID.dll),将两个dll文件考到java的class文件同一目录下面,运行java文件就可以了!!!





用jni生成一个C或者C++的dll,然后在那个dll里面调用你说的这个dll

用java直接调用是不行的

因为java调用的dll是必须准找一定的规则的,都是用javah生成本地方法的头文件,然后写c或着c++,然后编译成dll



例一

JAVA通过JNI调用本地C语言方法

JAVA以其跨平台的特性深受人们喜爱,而又正由于它的跨平台的目的,使得它和本地机器的各种内部联系变得很少,约束了它的功能。解决JAVA对本地操作的一种方法就是JNI。

JAVA通过JNI调用本地方法,而本地方法是以库文件的形式存放的(在WINDOWS平台上是DLL文件形式,在UNIX机器上是SO文件形式)。通过调用本地的库文件的内部方法,使JAVA可以实现和本地机器的紧密联系,调用系统级的各接口方法。

简单介绍及应用如下:

一、JAVA中所需要做的工作


在JAVA程序中,首先需要在类中声明所调用的库名称,如下:

static {


System.loadLibrary(“goodluck”);



}



在这里,库的扩展名字可以不用写出来,究竟是DLL还是SO,由系统自己判断。


还需要对将要调用的方法做本地声明,关键字为native。并且只需要声明,而不需要具体实现。如下:


public native static void set(int i);

public native static int get();

然后编译该JAVA程序文件,生成CLASS,再用JAVAH命令,JNI就会生成C/C++的头文件。



例如程序testdll.java,内容为:

public class testdll



{

static


{





System.loadLibrary("goodluck");





}



public native static int get();





public native static void set(int i);




public static void main(String[] args)





{





testdll test = new testdll();





test.set(10);





System.out.println(test.get());





}





}





用javac testdll.java编译它,会生成testdll.class。





再用javah testdll,则会在当前目录下生成testdll.h文件,这个文件需要被C/C++程序调用来生成所需的库文件。



二、C/C++中所需要做的工作





对于已生成的.h头文件,C/C++所需要做的,就是把它的各个方法具体的实现。然后编译连接成库文件即可。再把库文件拷贝到JAVA程序的路径下面,就可以用JAVA调用C/C++所实现的功能了。




接上例子。我们先看一下testdll.h文件的内容:





/* DO NOT EDIT THIS FILE - it is machine generated */





#include <jni.h>





/* Header for class testdll */



#ifndef _Included_testdll





#define _Included_testdll





#ifdef __cplusplus





extern "C" {





#endif





/*





* Class: testdll





* Method: get





* Signature: ()I





*/


JNIEXPORT jint JNICALL Java_testdll_get



(JNIEnv *, jclass);

/*

* Class: testdll





* Method: set





* Signature: (I)V





*/



JNIEXPORT void JNICALL Java_testdll_set



(JNIEnv *, jclass, jint);


#ifdef __cplusplus





}



#endif

#endif


在具体实现的时候,我们只关心两个函数原型


JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass);


JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint);





这里JNIEXPORT和JNICALL都是JNI的关键字,表示此函数是要被JNI调用的。而jint是以JNI为中介使JAVA的int类型与本地的int沟通的一种类型,我们可以视而不见,就当做int使用。函数的名称是JAVA_再加上java程序的package路径再加函数名组成的。参数中,我们也只需要关心在JAVA程序中存在的参数,至于JNIEnv*和jclass我们一般没有必要去碰它。





好,下面我们用testdll.cpp文件具体实现这两个函数:





#include "testdll.h"





int i = 0;





JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass)





{





return i;





}





JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint j)



{





i = j;





}





编译连接成库文件,本例是在WINDOWS下做的,生成的是DLL文件。并且名称要与JAVA中需要调用的一致,这里就是goodluck.dll




把goodluck.dll拷贝到testdll.class的目录下,java testdll运行它,就可以观察到结果了。



例二

一、JAVA中所需要做的工作





在JAVA程序中,首先需要在类中声明所调用的库名称,如下:



public class testdll {

static

{

System.loadLibrary("FANGJIAN");

}





public native static String ID_Read();









public static void main(String[] args)





{

testdll test = new testdll();

String a=test.ID_Read();

System.out.println(a);

}





}




用javac testdll.java编译它,会生成testdll.class。





再用javah testdll,则会在当前目录下生成testdll.h文件,这个文件需要被C/C++程序调用来生成所需的库文件。




二、C/C++中所需要做的工作

对于已生成的.h头文件,C/C++所需要做的,就是把它的各个方法具体的实现,此处就可以在方法体中调用厂家所提供的dll库文件,来实现调用,并获得返回值。然后编译连接成库文件即可。再把库文件和厂家提供的库文件拷贝到JAVA程序的路径下面,就可以用JAVA调用C/C++所实现的功能了。

需要注意的是必须将jni.h文件和jni_md.h文件考到c编译器的include文件夹下,这样才能通过编译!!!调用了这两个头文件里的声明……….

接上例子。我们先看一下testdll.h文件的内容:

/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

/* Header for class testdll */



#ifndef _Included_testdll

#define _Included_testdll

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class: testdll

* Method: ID_Read

* Signature: ()Ljava/lang/String;

*/

JNIEXPORT jstring JNICALL Java_testdll_ID_1Read(JNIEnv *, jclass);//方法名


#ifdef __cplusplus

}

#endif

#endif



在具体实现的时候,我们只关心这个函数原型

JNIEXPORT jstring JNICALL Java_testdll_ID_1Read(JNIEnv *, jclass);

如果是java类文件有包的话,函数的原型的名字会相应加上包名字

如:pakcage com.util; 原型变为:

JNIEXPORT jstring JNICALL Java_com_util_testdll_ID_1Read(JNIEnv *, jclass);



这里JNIEXPORT和JNICALL都是JNI的关键字,表示此函数是要被JNI调用的。而jint(jstring)是以JNI为中介使JAVA的int(string)类型与本地的int(string)沟通的一种类型,我们可以视而不见,就当做int(string)使用。函数的名称是JAVA_再加上java程序的package路径再加函数名组成的。参数中,我们也只需要关心在JAVA程序中存在的参数,至于JNIEnv*和jclass我们一般没有必要去碰它。


好,下面我们用testdll.cpp文件具体实现这两个函数


#include <iostream.h>

#include <windows.h>

#include <string.h>

#include <testdll.h>


typedef HANDLE (_stdcall *COMINT)(unsigned char port);

typedef int (_stdcall *COM_CLOSE)(HANDLE hr);

typedef int (_stdcall *ID_Read)(HANDLE icdev,int tt,unsigned char *_Data);


JNIEXPORT jstring JNICALL Java_testdll_ID_1Read(JNIEnv* env,jclass)

{

HINSTANCE hTest;

HANDLE hr;

COMINT pComInit;

COM_CLOSE pComClose;

ID_Read pRead;

int j;

unsigned char data[16]="put card on it",*A=data;

jstring jstr;

hTest=LoadLibrary("TF_ID.dll");

pComInit=(COMINT)GetProcAddress(hTest,"ComInit");

pComClose=(COM_CLOSE)GetProcAddress(hTest,"ComClose");

pRead=(ID_Read)GetProcAddress(hTest,"ID_Read");

hr=pComInit(1);

j=pRead(hr,3000,data);


char b[16]="put card on it",*B=b;

for(int i=0;i<16;i++)

*(B+i)=*(A+i);

jstr=env->NewStringUTF(b);



if(j==8)

return jstr;

else

return jstr;

pComClose(hr);

FreeLibrary(hTest);
}
其中进行了unsigned char【】到char【】的转换,并最后付给jstring中!!!

stdcall、cdecl的区别!!!

编译连接成库文件,本例是在WINDOWS下做的,生成的是DLL文件。并且名称要与JAVA中需要调用的一致,这里就是FANGJIAN.dll

把FANGJIAN.dll和TF_ID.dll(或考TF_ID.dll到system32下)拷贝到testdll.class的目录下,java testdll运行它,就可以观察到结果了。
Jacob 是Java-COM Bridge的缩写,它在Java与微软的COM组件之间构建一座桥梁。使用Jacob自带的DLL动态链接库,并通过JNI的方式实现了在Java平台上对COM程序的调用。
eclipse 启动参数
===========================================================
直接右键eclipse的快捷方式,在"目标"中填入下行

D:eclipseeclipse.exe -debug options -vm javaw.exe -nl en_US -clean -vmargs -Xverify:none -XX:+UseParallelGC -XX:PermSize=20M -XX:MaxNewSize=32M -XX:NewSize=32M -Xms128m -Xmx256m

参数注解:

【-debug options -vm javaw.exe】 显示JVM当前内存使用量(注:详见下方《让你的eclipse也能显示JVM当前内存使用量》)

【-nl】后面跟的是语言:英语 en_US 简体中文 zh_CN

【-clean 】是当启动Eclipse IDE时清空缓冲,一般来说在没有更新插件的情况下,去掉这个参数启动速度更快。

【-vmargs】使用JRE的参数,后面就是JRE的参数了:

【-Xverify:none】去掉JAR包数据验证,一般来说只有在网络环境下才需要验证JAR包数据的有效性。本地的话可以不用验证。

【-XX:+UseParallelGC】使用并行垃圾收集机制,据说这个GC算法比较快。具体不清楚。

【-XX:PermSize=20M -XX:MaxNewSize=32M -XX:NewSize=32M】这三个就是设置详细的缓冲数据了。详情看Java官方网站的介绍吧。

【-Xms128m】Java虚拟机初始化内存容量。

【-Xmx256m】Java虚拟机最大使用内存容量,根据你所使用机器的内容大小设置,只要不超过最大内存容量就好。

《让你的eclipse也能显示JVM当前内存使用量》

1、在eclipse根目录下建立一个文件,文件名options,文件内容:org.eclipse.ui/perf/showHeapStatus=true

2、用这条命令启动Eclipse:D:eclipseeclipse.exe -debug options -vm javaw.exe

或者直接右键eclipse的快捷方式,在"目标"中填入这行。

3、启动eclipse,就可以看到下面的状态栏会显示当前JVM内存使用量,另外还可以强制进行垃圾收集。

修改那个ini文件是要注意,修改文件之前一定要注意备份。
加启动参数和在ini中写是一样的,都是启动的配置。

eclipse对于jre的加载顺序:首先执行 -vm 参数;如果没有 -vm 参数,则查找 eclipsejre 子目录;如果没有找到,eclipse最后才查找在系统中注册的jre。
下载 poi 包

public class TestPoiExcel {
static Log log = LogFactory.getLog(TestPoiExcel.class);

public static String fileToBeRead="e://test.xls";
public static void main(String argv[]) {
try {
// 创建对Excel工作簿文件的引用
HSSFWorkbook workbook= new HSSFWorkbook(new FileInputStream(fileToBeRead));
// 创建对工作表的引用。
//   本例是按名引用(让我们假定那张表有着缺省名"Sheet1")
// 也可用getSheetAt(int index)按索引引用,
//   在Excel文档中,第一张工作表的缺省索引是0,
//   其语句为:HSSFSheet sheet = workbook.getSheetAt(0);
HSSFSheet sheet= workbook.getSheet("Sheet1");
int rows = sheet.getPhysicalNumberOfRows();
for (int r = 0; r < rows; r++) {
//   读取左上端单元
HSSFRow row = sheet.getRow(r);
if (row != null) {
int cells = row.getPhysicalNumberOfCells();
String value = "";
// log.info(cells);
for (short c = 0; c < cells; c++) {
HSSFCell cell = row.getCell(c);
if (cell != null){
switch (cell.getCellType()) {

case HSSFCell.CELL_TYPE_FORMULA :
//
break;

case HSSFCell.CELL_TYPE_NUMERIC:
value += (long)cell.getNumericCellValue()+",";
break;

case HSSFCell.CELL_TYPE_STRING:
value += cell.getStringCellValue()+",";
break;

default:
value +="0,";
}
}
}
//下面可以将查找到的行内容用SQL语句INSERT到oracle
log.info(value);
}
}
}catch(Exception e){
System.out.println(e);
}
}

}
C:Documents and Settingsmeteor>jar -help
非法选项:h
用法:jar {ctxu}[vfm0Mi] [jar-文件] [manifest-文件] [-C 目录] 文件名 ...
选项:
-c 创建新的存档
-t 列出存档内容的列表
-x 展开存档中的命名的(或所有的〕文件
-u 更新已存在的存档
-v 生成详细输出到标准输出上
-f 指定存档文件名
-m 包含来自标明文件的标明信息
-0 只存储方式;未用ZIP压缩格式
-M 不产生所有项的清单(manifest〕文件
-i 为指定的jar文件产生索引信息
-C 改变到指定的目录,并且包含下列文件:
如果一个文件名是一个目录,它将被递归处理。
清单(manifest〕文件名和存档文件名都需要被指定,按'm' 和 'f'标志指定的相同顺序。

示例1:将两个class文件存档到一个名为 'classes.jar' 的存档文件中:
jar cvf classes.jar Foo.class Bar.class
示例2:用一个存在的清单(manifest)文件 'mymanifest' 将 foo/ 目录下的所有
文件存档到一个名为 'classes.jar' 的存档文件中:
jar cvfm classes.jar mymanifest -C foo/ .


C:Documents and Settingsmeteor>cd E:projectpasgzshWebRootWEB-INFlib

C:Documents and Settingsmeteor>cd e:
E:projectpasgzshWebRootWEB-INFlib

C:Documents and Settingsmeteor>cd
C:Documents and Settingsmeteor

C:Documents and Settingsmeteor>cd..

C:Documents and Settings>cd..

C:>e:

E:projectpasgzshWebRootWEB-INFlib>jar cvf SdkLog4jConfig.jar SdkLog4jConfig
.xml
标明清单(manifest)
增加:SdkLog4jConfig.xml(读入= 1129) (写出= 485)(压缩了 57%)

E:projectpasgzshWebRootWEB-INFlib>jar cvf default-domain.jar default-domain
.cfg
标明清单(manifest)
增加:default-domain.cfg(读入= 14738) (写出= 3519)(压缩了 76%)
原创粉丝点击