How to alter / refactor method to use FileInputStream for a local file along with InputStream for a URL using Java 1.8?

huangapple go评论128阅读模式
英文:

How to alter / refactor method to use FileInputStream for a local file along with InputStream for a URL using Java 1.8?

问题

使用Java 1.8,我创建了一个类,该类从外部HTTP URL获取一个zip文件:

例如:

https://raw.githubusercontent.com/mlampros/DataSets/master/fastText_data.zip

并将其转换为基于字符串的MD5哈希值:

6aa2fe666f83953a089a2caa8b13b80e

我的实用工具类:

public class HashUtils {
 
    public static String makeHashFromUrl(String fileUrl) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            InputStream is = new URL(fileUrl).openStream();

            try {
                is = new DigestInputStream(is, md);

                // 每次读取最多8K
                byte[] ignoredBuffer = new byte[8 * 1024];

                while (is.read(ignoredBuffer) > 0) { }
            } finally {
                is.close();
            }
            byte[] digest = md.digest();
            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < digest.length; i++) {
                sb.append(Integer.toString((digest[i] & 0xff) + 0x100, 16).substring(1));
            }
            return sb.toString();

        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }
}

虽然这对于包含zip文件(或具有任何类型文件扩展名的文件)的外部URL是可以的,但我需要能够对位于本地文件系统上的文件使用相同的代码(算法)。

例如:

$CATALINA_HOME/temp/fastText_data.zip

需要改用:

InputStream fis = new FileInputStream(filename);

如何在不违反DRY(不要重复自己)原则的情况下使用相同的方法进行此操作?

当然,创建一个全新的方法,其中包含相同的代码,但使用 InputStream fis = new FileInputStream(filename); 替代 InputStream is = new URL(fileUrl).openStream(); 将违反DRY原则?

重构的一个好方法是什么?两个公共方法,其中一个重构的私有方法包含相同的代码行?

英文:

Using Java 1.8, I created a class which obtains a zip file from an external HTTP URL:

e.g.

https://raw.githubusercontent.com/mlampros/DataSets/master/fastText_data.zip

and converts it into a String based MD5 hash:

6aa2fe666f83953a089a2caa8b13b80e

My utility class:

public class HashUtils {
 
    public static String makeHashFromUrl(String fileUrl) {
        try {
            MessageDigest md = MessageDigest.getInstance(&quot;MD5&quot;);
            InputStream is = new URL(fileUrl).openStream();

            try {
                is = new DigestInputStream(is, md);

                // Up to 8K per read
                byte[] ignoredBuffer = new byte[8 * 1024];

                while (is.read(ignoredBuffer) &gt; 0) { }
            } finally {
                is.close();
            }
            byte[] digest = md.digest();
            StringBuilder sb = new StringBuilder();

            for (int i = 0; i &lt; digest.length; i++) {
                sb.append(Integer.toString((digest[i] &amp; 0xff) + 0x100, 16).substring(1));
            }
            return sb.toString();

        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }
}

Whereas this is fine for an external URL containing zip file (or any file with any type of file extension), I need to be be able to use the same code (algorithm) for files that reside on a local filesystem.

e.g.

Inside $CATALINA_HOME/temp/fastText_data.zip

Would need to use this instead:

InputStream fis =  new FileInputStream(filename);

How could I do this using the same method (don't want to violate DRY - Don't Repeat Yourself)?

Of course, creating a brand new method containing the same code but using the InputStream fis = new FileInputStream(filename); instead of InputStream is = new URL(fileUrl).openStream(); would be violating the DRY principle?

What would be a good way to refactor this out? Two public methods with a refactored private method containing the same lines of code?

答案1

得分: 3

创建三个方法:一个私有方法,它期望一个InputStream参数,该参数将传递给您当前的逻辑;以及两个非常简短的公共方法,它们分别使用它们创建的InputStream调用私有方法。

public static String makeHashFromUrl(String url) {
    try (InputStream stream = new URL(url).openStream()) {
        return makeHashFromStream(stream);
    }
}

public static String makeHashFromFile(File file) {
    try (InputStream stream = new BufferedInputStream(new FileInputStream(file))) {
        return makeHashFromStream(stream);
    }
}

private static String makeHashFromStream(InputStream is) {
    try {
        MessageDigest md = MessageDigest.getInstance("MD5");

        try {
            is = new DigestInputStream(is, md);

            // 等等。
        }
英文:

Make three methods: A private method that expects an InputStream argument which is given to your current logic, and two very short public methods which each call the private method with an InputStream they create.

public static String makeHashFromUrl(String url) {
    try (InputStream stream = new URL(url).openStream()) {
        return makeHashFromStream(stream);
    }
}

public static String makeHashFromFile(File file) {
    try (InputStream stream = new BufferedInputStream(new FileInputStream(file))) {
        return makeHashFromStream(stream);
    }
}

private static String makeHashFromStream(InputStream is) {
    try {
        MessageDigest md = MessageDigest.getInstance(&quot;MD5&quot;);

        try {
            is = new DigestInputStream(is, md);

            // etc.
}

huangapple
  • 本文由 发表于 2020年7月24日 10:17:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/63065794.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定