Каталог копии из файла банки

Например,

package main

import (
    "fmt"
    "time"
)

func main() {
    type example struct {
        CreatedAt int64 `parquet:"name=created_at,type=TIMESTAMP_MILLIS"`
    }

    ex := example{}
    ex.CreatedAt = time.Now().UnixNano() / int64(time.Millisecond)
    fmt.Println(ex.CreatedAt)
}

Детская площадка: https://play.golang.org/p/ePOlUKiT6fD

Вывод:

1257894000000

32
задан Michael Petrotta 21 August 2012 в 06:01
поделиться

6 ответов

Я думаю, что ваш подход к использованию zip-файла имеет смысл. Предположительно, вы выполните getResourceAsStream , чтобы получить доступ к внутренней части zip-архива, который логически будет выглядеть как дерево каталогов.

Скелетный подход:

InputStream is = getClass().getResourceAsStream("my_embedded_file.zip");
ZipInputStream zis = new ZipInputStream(is);
ZipEntry entry;

while ((entry = zis.getNextEntry()) != null) {
    // do something with the entry - for example, extract the data 
}
11
ответ дан 27 November 2019 в 20:39
поделиться

Я знаю, что этот вопрос довольно стар теперь, но после попытки некоторых ответов, которые не работали и другие, которые потребовали целой библиотеки всего для одного метода, я решил соединить класс. Это не требует сторонних библиотек, и это было протестировано с Java 8. Существует четыре открытых метода: copyResourcesToTempDir, copyResourcesToDir, copyResourceDirectory и jar.

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.nio.file.Files;
import java.util.Enumeration;
import java.util.Optional;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * A helper to copy resources from a JAR file into a directory.
 */
public final class ResourceCopy {

    /**
     * URI prefix for JAR files.
     */
    private static final String JAR_URI_PREFIX = "jar:file:";

    /**
     * The default buffer size.
     */
    private static final int BUFFER_SIZE = 8 * 1024;

    /**
     * Copies a set of resources into a temporal directory, optionally preserving
     * the paths of the resources.
     * @param preserve Whether the files should be placed directly in the
     *  directory or the source path should be kept
     * @param paths The paths to the resources
     * @return The temporal directory
     * @throws IOException If there is an I/O error
     */
    public File copyResourcesToTempDir(final boolean preserve,
        final String... paths)
        throws IOException {
        final File parent = new File(System.getProperty("java.io.tmpdir"));
        File directory;
        do {
            directory = new File(parent, String.valueOf(System.nanoTime()));
        } while (!directory.mkdir());
        return this.copyResourcesToDir(directory, preserve, paths);
    }

    /**
     * Copies a set of resources into a directory, preserving the paths
     * and names of the resources.
     * @param directory The target directory
     * @param preserve Whether the files should be placed directly in the
     *  directory or the source path should be kept
     * @param paths The paths to the resources
     * @return The temporal directory
     * @throws IOException If there is an I/O error
     */
    public File copyResourcesToDir(final File directory, final boolean preserve,
        final String... paths) throws IOException {
        for (final String path : paths) {
            final File target;
            if (preserve) {
                target = new File(directory, path);
                target.getParentFile().mkdirs();
            } else {
                target = new File(directory, new File(path).getName());
            }
            this.writeToFile(
                Thread.currentThread()
                    .getContextClassLoader()
                    .getResourceAsStream(path),
                target
            );
        }
        return directory;
    }

    /**
     * Copies a resource directory from inside a JAR file to a target directory.
     * @param source The JAR file
     * @param path The path to the directory inside the JAR file
     * @param target The target directory
     * @throws IOException If there is an I/O error
     */
    public void copyResourceDirectory(final JarFile source, final String path,
        final File target) throws IOException {
        final Enumeration<JarEntry> entries = source.entries();
        final String newpath = String.format("%s/", path);
        while (entries.hasMoreElements()) {
            final JarEntry entry = entries.nextElement();
            if (entry.getName().startsWith(newpath) && !entry.isDirectory()) {
                final File dest =
                    new File(target, entry.getName().substring(newpath.length()));
                final File parent = dest.getParentFile();
                if (parent != null) {
                    parent.mkdirs();
                }
                this.writeToFile(source.getInputStream(entry), dest);
            }
        }
    }

    /**
     * The JAR file containing the given class.
     * @param clazz The class
     * @return The JAR file or null
     * @throws IOException If there is an I/O error
     */
    public Optional<JarFile> jar(final Class<?> clazz) throws IOException {
        final String path =
            String.format("/%s.class", clazz.getName().replace('.', '/'));
        final URL url = clazz.getResource(path);
        Optional<JarFile> optional = Optional.empty();
        if (url != null) {
            final String jar = url.toString();
            final int bang = jar.indexOf('!');
            if (jar.startsWith(ResourceCopy.JAR_URI_PREFIX) && bang != -1) {
                optional = Optional.of(
                    new JarFile(
                        jar.substring(ResourceCopy.JAR_URI_PREFIX.length(), bang)
                    )
                );
            }
        }
        return optional;
    }

    /**
     * Writes an input stream to a file.
     * @param input The input stream
     * @param target The target file
     * @throws IOException If there is an I/O error
     */
    private void writeToFile(final InputStream input, final File target)
        throws IOException {
        final OutputStream output = Files.newOutputStream(target.toPath());
        final byte[] buffer = new byte[ResourceCopy.BUFFER_SIZE];
        int length = input.read(buffer);
        while (length > 0) {
            output.write(buffer, 0, length);
            length = input.read(buffer);
        }
        input.close();
        output.close();
    }

}
0
ответ дан 27 November 2019 в 20:39
поделиться

Я не уверен, что такое FileHelper , но вы НЕ сможете копировать файлы (или каталоги) непосредственно из JAR. Использование InputStream, как вы упомянули, является правильным способом (из jar или zip-архива):

InputStream is = getClass().getResourceAsStream("file_in_jar");
OutputStream os = new FileOutputStream("dest_file");
byte[] buffer = new byte[4096];
int length;
while ((length = is.read(buffer)) > 0) {
    os.write(buffer, 0, length);
}
os.close();
is.close();

Вам нужно будет сделать вышеупомянутое (конечно, обрабатывать исключения соответствующим образом) для каждого из ваших файлов. Вы можете или не сможете (в зависимости от конфигурации развертывания) прочитать рассматриваемый файл jar как JarFile (он может быть недоступен как фактический файл, если развернут как часть нерасширенного веб-приложения, для пример). Если вы можете его прочитать, вы сможете перебирать список экземпляров JarEntry и таким образом восстанавливать структуру каталогов; в противном случае вам может потребоваться сохранить его в другом месте (в текстовом или xml-ресурсе,

3
ответ дан 27 November 2019 в 20:39
поделиться

Вы можете использовать ClassLoader для получения потока к ресурсу . После того, как вы получили InputStream, вы можете считать и записать содержимое потока в OutputStream.

В вашем случае вам нужно будет создать несколько экземпляров OutputStream, по одному для каждого файла, который вы хотите скопировать. к месту назначения. Это, конечно, требует, чтобы вы заранее знали имена файлов.

Для этой задачи предпочтительно использовать getResourceAsStream, а не getResource или getResources ().

2
ответ дан 27 November 2019 в 20:39
поделиться

Мне не понравилась идея использования метода ZIP-файла, опубликованная ранее, поэтому я придумал следующее.

public void copyResourcesRecursively(URL originUrl, File destination) throws Exception {
    URLConnection urlConnection = originUrl.openConnection();
    if (urlConnection instanceof JarURLConnection) {
        copyJarResourcesRecursively(destination, (JarURLConnection) urlConnection);
    } else if (urlConnection instanceof FileURLConnection) {
        FileUtils.copyFilesRecursively(new File(originUrl.getPath()), destination);
    } else {
        throw new Exception("URLConnection[" + urlConnection.getClass().getSimpleName() +
                "] is not a recognized/implemented connection type.");
    }
}

public void copyJarResourcesRecursively(File destination, JarURLConnection jarConnection ) throws IOException {
    JarFile jarFile = jarConnection.getJarFile();
    for (JarEntry entry : CollectionUtils.iterable(jarFile.entries())) {
        if (entry.getName().startsWith(jarConnection.getEntryName())) {
            String fileName = StringUtils.removeStart(entry.getName(), jarConnection.getEntryName());
            if (!entry.isDirectory()) {
                InputStream entryInputStream = null;
                try {
                    entryInputStream = jarFile.getInputStream(entry);
                    FileUtils.copyStream(entryInputStream, new File(destination, fileName));
                } finally {
                    FileUtils.safeClose(entryInputStream);
                }
            } else {
                FileUtils.ensureDirectoryExists(new File(destination, fileName));
            }
        }
    }
}

Пример использования (копирует все файлы из ресурса пути к классам "config" в "$ {homeDirectory} / config":

File configHome = new File(homeDirectory, "config/");
//noinspection ResultOfMethodCallIgnored
configHome.mkdirs();
copyResourcesRecursively(super.getClass().getResource("/config"), configHome);

Это должно работать как для копирования из плоских файлов, так и из файлов Jar.

Примечание: В приведенном выше коде используются некоторые пользовательские служебные классы (FileUtils, CollectionUtils), а также некоторые из Apache commons-lang (StringUtils), но названия функций должны быть достаточно очевидными.

6
ответ дан 27 November 2019 в 20:39
поделиться

Спасибо за решение! Для других следующие не используют вспомогательные классы (кроме StringUtils)

/ Я добавил дополнительную информацию для этого решения, проверьте конец кода, Zegor V /

public class FileUtils {
  public static boolean copyFile(final File toCopy, final File destFile) {
    try {
      return FileUtils.copyStream(new FileInputStream(toCopy),
          new FileOutputStream(destFile));
    } catch (final FileNotFoundException e) {
      e.printStackTrace();
    }
    return false;
  }

  private static boolean copyFilesRecusively(final File toCopy,
      final File destDir) {
    assert destDir.isDirectory();

    if (!toCopy.isDirectory()) {
      return FileUtils.copyFile(toCopy, new File(destDir, toCopy.getName()));
    } else {
      final File newDestDir = new File(destDir, toCopy.getName());
      if (!newDestDir.exists() && !newDestDir.mkdir()) {
        return false;
      }
      for (final File child : toCopy.listFiles()) {
        if (!FileUtils.copyFilesRecusively(child, newDestDir)) {
          return false;
        }
      }
    }
    return true;
  }

  public static boolean copyJarResourcesRecursively(final File destDir,
      final JarURLConnection jarConnection) throws IOException {

    final JarFile jarFile = jarConnection.getJarFile();

    for (final Enumeration<JarEntry> e = jarFile.entries(); e.hasMoreElements();) {
      final JarEntry entry = e.nextElement();
      if (entry.getName().startsWith(jarConnection.getEntryName())) {
        final String filename = StringUtils.removeStart(entry.getName(), //
            jarConnection.getEntryName());

        final File f = new File(destDir, filename);
        if (!entry.isDirectory()) {
          final InputStream entryInputStream = jarFile.getInputStream(entry);
          if(!FileUtils.copyStream(entryInputStream, f)){
            return false;
          }
          entryInputStream.close();
        } else {
          if (!FileUtils.ensureDirectoryExists(f)) {
            throw new IOException("Could not create directory: "
                + f.getAbsolutePath());
          }
        }
      }
    }
    return true;
  }

  public static boolean copyResourcesRecursively( //
      final URL originUrl, final File destination) {
    try {
      final URLConnection urlConnection = originUrl.openConnection();
      if (urlConnection instanceof JarURLConnection) {
        return FileUtils.copyJarResourcesRecursively(destination,
            (JarURLConnection) urlConnection);
      } else {
        return FileUtils.copyFilesRecusively(new File(originUrl.getPath()),
            destination);
      }
    } catch (final IOException e) {
      e.printStackTrace();
    }
    return false;
  }

  private static boolean copyStream(final InputStream is, final File f) {
    try {
      return FileUtils.copyStream(is, new FileOutputStream(f));
    } catch (final FileNotFoundException e) {
      e.printStackTrace();
    }
    return false;
  }

  private static boolean copyStream(final InputStream is, final OutputStream os) {
    try {
      final byte[] buf = new byte[1024];

      int len = 0;
      while ((len = is.read(buf)) > 0) {
        os.write(buf, 0, len);
      }
      is.close();
      os.close();
      return true;
    } catch (final IOException e) {
      e.printStackTrace();
    }
    return false;
  }

  private static boolean ensureDirectoryExists(final File f) {
    return f.exists() || f.mkdir();
  }
}

Он использует только одну внешнюю библиотеку от Apache Software Foundation, однако используются только следующие функции:

  public static String removeStart(String str, String remove) {
      if (isEmpty(str) || isEmpty(remove)) {
          return str;
      }
      if (str.startsWith(remove)){
          return str.substring(remove.length());
      }
      return str;
  }
  public static boolean isEmpty(CharSequence cs) {
      return cs == null || cs.length() == 0;
  }

Мои знания ограничены лицензией Apache, но вы можете использовать эти методы в своем коде без библиотеки. Однако я не несу ответственности за проблемы с лицензией, если они есть.

16
ответ дан 27 November 2019 в 20:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: