Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/398.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用Java在OSX上的扩展文件属性中存储哈希?_Java_Macos_Metadata_Hfs+_Xattr - Fatal编程技术网

如何使用Java在OSX上的扩展文件属性中存储哈希?

如何使用Java在OSX上的扩展文件属性中存储哈希?,java,macos,metadata,hfs+,xattr,Java,Macos,Metadata,Hfs+,Xattr,前言 我在一个用java编写的媒体数据库平台上工作,在这个平台上,媒体文件由文件散列标识。用户应该能够移动文件,所以我不想依赖任何文件路径。导入后,我将路径和哈希存储在数据库中。 我基于准确性和性能之间的折衷开发了一种新的方法,但快速并不总是足够快。:) 为了更新和导入媒体文件,我需要(重新)创建库中所有文件的文件哈希。我现在的想法是只计算一次散列并将其存储在文件元数据(扩展属性)中,以提高支持扩展文件属性的文件系统的性能。(NTFS、HFS+、ext3…) 我已经实现了它,您可以在这里找到当前

前言 我在一个用java编写的媒体数据库平台上工作,在这个平台上,媒体文件由文件散列标识。用户应该能够移动文件,所以我不想依赖任何文件路径。导入后,我将路径和哈希存储在数据库中。 我基于准确性和性能之间的折衷开发了一种新的方法,但快速并不总是足够快。:)

为了更新和导入媒体文件,我需要(重新)创建库中所有文件的文件哈希。我现在的想法是只计算一次散列并将其存储在文件元数据(扩展属性)中,以提高支持扩展文件属性的文件系统的性能。(NTFS、HFS+、ext3…) 我已经实现了它,您可以在这里找到当前的源代码:

尝试 乍一看,Java1.7提供了一种处理元数据的好方法。对于大多数平台,这是可行的。遗憾的是,UserDefinedFileAttributeView在HFS+上不起作用。尽管如此,我不明白为什么不支持HFS+文件系统——它是元数据的主要格式之一?(参见相关-不提供任何解决方案)

如何使用Java在OS X上存储扩展文件属性? 为了克服java的这一局限性,我决定使用OSX上的命令行工具,并将其与java进程处理一起使用,从中读取输出。工作正常,但速度很慢。(文件散列的重新计算速度更快,真是讽刺!我正在一台装有SSD的MacBookPro视网膜上进行测试。)

事实证明,xattr工具的工作速度相当慢。(写入速度非常慢,但更重要的是读取属性也非常慢) 为了证明这不是Java问题,而是工具本身的问题,我创建了一个简单的bash脚本,在几个具有我的自定义属性的文件上使用xattr工具:

FILES=/Users/IsNull/Pictures/
for f in $FILES
do
  xattr -p vidada.hash $f
done
如果我运行它,这些行会依次显示为“快”,但我希望在毫秒内立即显示输出。有一点延迟是显而易见的,因此我猜工具没有那么快。在java中使用它会给我额外的创建进程的开销,解析输出,这会使它变得更慢


是否有更好的方法使用Java访问HFS+上的扩展属性?使用Java在OS X上使用扩展属性的快速方法是什么?

OS X的
/usr/bin/xattr
可能相当慢,因为它是作为Python脚本实现的。用于设置扩展属性的C API是。下面是一个例子:

if(setxattr("/path/to/file",
            attribute_name,
            (void *)attribute_data,
            attribute_size,
            0,
            XATTR_NOFOLLOW) != 0)
{
  /* an error occurred, see errno */
}

您可以创建一个JNI包装器来从Java访问这个函数;您可能还需要getxattr(2)、listxattr(2)和removexattr(2),这取决于您的应用程序还需要做什么。

我已经创建了一个JNI包装器,用于直接通过C-API访问扩展属性。这是一个开源Java Maven项目,可在

为了便于参考,我在这里发布了一些有趣的源代码。有关最新资料来源,请参阅上述项目页面

Xattrj.java

public class Xattrj {

    /**
     * Write the extended attribute to the given file
     * @param file
     * @param attrKey
     * @param attrValue
     */
    public void writeAttribute(File file, String attrKey, String attrValue){
        writeAttribute(file.getAbsolutePath(), attrKey, attrValue);
    }

    /**
     * Read the extended attribute from the given file
     * @param file
     * @param attrKey
     * @return
     */
    public String readAttribute(File file, String attrKey){
        return readAttribute(file.getAbsolutePath(), attrKey);
    }

    /**
     * Write the extended attribute to the given file
     * @param file
     * @param attrKey
     * @param attrValue
     */
    private native void writeAttribute(String file, String attrKey, String attrValue);

    /**
     * Read the extended attribute from the given file
     * @param file
     * @param attrKey
     * @return
     */
    private native String readAttribute(String file, String attrKey);


    static {
        try {
            System.out.println("loading xattrj...");
            LibraryLoader.loadLibrary("xattrj");
            System.out.println("loaded!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
org\u securityvision\u xattrj\u xattrj.cpp

#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "org_securityvision_xattrj_Xattrj.h"
#include <sys/xattr.h>


/**
 * writeAttribute
 * writes the extended attribute
 *
 */
JNIEXPORT void JNICALL Java_org_securityvision_xattrj_Xattrj_writeAttribute
    (JNIEnv *env, jobject jobj, jstring jfilePath, jstring jattrName, jstring jattrValue){

    const char *filePath= env->GetStringUTFChars(jfilePath, 0);
    const char *attrName= env->GetStringUTFChars(jattrName, 0);
    const char *attrValue=env->GetStringUTFChars(jattrValue,0);

    int res = setxattr(filePath,
                attrName,
                (void *)attrValue,
                strlen(attrValue), 0,  0); //XATTR_NOFOLLOW != 0
    if(res){
      // an error occurred, see errno
        printf("native:writeAttribute: error on write...");
        perror("");
    }
}


/**
 * readAttribute
 * Reads the extended attribute as string
 *
 * If the attribute does not exist (or any other error occurs)
 * a null string is returned.
 *
 *
 */
JNIEXPORT jstring JNICALL Java_org_securityvision_xattrj_Xattrj_readAttribute
    (JNIEnv *env, jobject jobj, jstring jfilePath, jstring jattrName){

    jstring jvalue = NULL;

    const char *filePath= env->GetStringUTFChars(jfilePath, 0);
    const char *attrName= env->GetStringUTFChars(jattrName, 0);

    // get size of needed buffer
    int bufferLength = getxattr(filePath, attrName, NULL, 0, 0, 0);

    if(bufferLength > 0){
        // make a buffer of sufficient length
        char *buffer = (char*)malloc(bufferLength);

        // now actually get the attribute string
        int s = getxattr(filePath, attrName, buffer, bufferLength, 0, 0);

        if(s > 0){
            // convert the buffer to a null terminated string
            char *value = (char*)malloc(s+1);
            *(char*)value = 0;
            strncat(value, buffer, s);
            free(buffer);

            // convert the c-String to a java string
            jvalue = env->NewStringUTF(value);
        }
    }
    return jvalue;
}
#包括
#包括
#包括
#包括
#包括“org\u securityvision\u xattrj\u xattrj.h”
#包括
/**
*书写属性
*写入扩展属性
*
*/
JNIEXPORT void JNICALL Java_org_securityvision_xattrj_xattrj_writeAttribute
(JNIEnv*env、jobject-jobj、jstring-jfilePath、jstring-jattrName、jstring-jattrValue){
const char*filePath=env->GetStringUTFChars(jfilePath,0);
const char*attrName=env->GetStringUTFChars(jattrName,0);
const char*attrValue=env->GetStringUTFChars(jattrValue,0);
int res=setxattr(文件路径,
属性名,
(void*)属性值,
strlen(attrValue),0,0);//XATTR\u NOFOLLOW!=0
如果(res){
//发生错误,请参阅错误号
printf(“本机:writeAttribute:写入时出错…”);
佩罗尔(“”);
}
}
/**
*readAttribute
*将扩展属性作为字符串读取
*
*如果属性不存在(或发生任何其他错误)
*返回空字符串。
*
*
*/
JNIEXPORT jstring JNICALL Java_org_securityvision_xattrj_xattrj_readAttribute
(JNIEnv*env、jobject-jobj、jstring-jfilePath、jstring-jattrName){
jstring jvalue=NULL;
const char*filePath=env->GetStringUTFChars(jfilePath,0);
const char*attrName=env->GetStringUTFChars(jattrName,0);
//获取所需缓冲区的大小
int bufferLength=getxattr(filePath,attrName,NULL,0,0,0);
如果(缓冲长度>0){
//做一个足够长的缓冲区
char*buffer=(char*)malloc(bufferLength);
//现在实际获取属性字符串
int s=getxattr(文件路径,属性名,缓冲区,缓冲区长度,0,0);
如果(s>0){
//将缓冲区转换为以null结尾的字符串
字符*值=(字符*)malloc(s+1);
*(char*)值=0;
strncat(值、缓冲区、s);
自由(缓冲);
//将c字符串转换为java字符串
jvalue=env->NewStringUTF(值);
}
}
返回jvalue;
}
现在,makefile让我有点困扰,无法让事情正常运行:

CC=gcc
LDFLAGS= -fPIC -bundle
CFLAGS= -c -shared -I/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers -m64


SOURCES_DIR=src/main/c++
OBJECTS_DIR=target/c++
EXECUTABLE=target/classes/libxattrj.dylib

SOURCES=$(shell find '$(SOURCES_DIR)' -type f -name '*.cpp')
OBJECTS=$(SOURCES:$(SOURCES_DIR)/%.cpp=$(OBJECTS_DIR)/%.o)

all: $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
    $(CC) $(LDFLAGS) $(OBJECTS) -o $@

$(OBJECTS): $(SOURCES)
    mkdir -p $(OBJECTS_DIR)
    $(CC) $(CFLAGS) $< -o $@



clean:
    rm -rf $(OBJECTS_DIR) $(EXECUTABLE)
CC=gcc
LDFLAGS=-fPIC-bundle
CFLAGS=-c-shared-I/System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers-m64
SOURCES\u DIR=src/main/c++
对象\u DIR=目标/c++
可执行文件=target/classes/libxattrj.dylib
SOURCES=$(shell查找'$(SOURCES_DIR)'-type f-name'*.cpp')
对象=$(源:$(源目录)/%.cpp=$(对象目录)/%.o)
全部:$(可执行)
$(可执行文件):$(对象)
$(CC)$(LDFLAGS)$(对象)-o$@
$(对象):$(源)
mkdir-p$(对象目录)
$(CC)$(CFLAGS)$<-o$@
清洁:
rm-rf$(对象\u目录)$(可执行文件)

我刚刚将我的
JNA包装器贡献给了JNA平台项目。因为它是JNA,所以您不需要编译