众所周知,MANIFEST.MF文件中的空格开头的行是相当于拼接在上一行末尾的。很多又长又乱的Import-Package或者Export-Package,有时候想要搜索某个package却可能被换行截断而搜不到。

这时候咱们可以对它进行格式化重新排列,同时又不影响它的正常运行。再排个序方便查找。

排列前 vs 排列后

附上干货 !!!

(脚本方式,对于长一点的package慢的一批,待优化;可对jar文件直接执行,免解压读取META-INF/MANIFEST.MF)

#!/bin/bash

# MANIFEST.MF文件对Import-Package/Export-Package重排列
function main() {
echo $ | egrep ".jar$|.zip$" &>/dev/null
if [ $? -eq ];then
MANIFEST=$(unzip -p $ META-INF/MANIFEST.MF)
[ $? -ne ] && echo ${MANIFEST} && exit
else
MANIFEST=$(cat $)
fi
isWindowsDoc="false"
# 判断文件格式是windows还是unix
[ "" != "$(echo "$MANIFEST" | sed -n ":a;N;/\r\n/p;ba")" ] && isWindowsDoc="true"
MANIFEST=$(echo "$MANIFEST" | dos2unix) # 空格开头的行,合并到一行
MANIFEST=$(echo "$MANIFEST" | sed ":a;N;s/\n //g;ba") importPackage=$(echo "${MANIFEST}" | egrep "^Import-Package:" | sed 's/^Import-Package: *//g' | sed 's/ //g')
exportPackage=$(echo "${MANIFEST}" | egrep "^Export-Package:" | sed 's/^Export-Package: *//g' | sed 's/ //g') output=$(echo "${MANIFEST}")
# 引号外的逗号转为特殊分隔符
if [ "" != "${importPackage}" ];then
importPackage=$(dealStrByPython ${importPackage})
importPackage="Import-Package: \n${importPackage}"
len=${#importPackage}
importPackage=$(echo -e "${importPackage:0:$((len-1))}") # 去掉最后一个字符
oneLineImport=$(echo "${importPackage}" | sed ":a;N;s/\n/#/g;ba") # sed命令不能一行换多行,将换行符转为#号变成一行,替换后#号再转回换行符
output=$(echo "${output}" | sed 's/^Import-Package:.*/'"${oneLineImport}"'/g' | sed "s/#/\n/g")
fi
if [ "" != "${exportPackage}" ];then
exportPackage=$(dealStrByPython ${exportPackage})
exportPackage="Export-Package: \n${exportPackage}"
len=${#exportPackage}
exportPackage=$(echo -e "${exportPackage:0:$((len-1))}")
oneLineExport=$(echo "${exportPackage}" | sed ":a;N;s/\n/#/g;ba")
output=$(echo "${output}" | sed 's/^Export-Package:.*/'"${oneLineExport}"'/g' | sed "s/#/\n/g")
fi if [ "true" == "${isWindowsDoc}" ];then
echo "${output}" | unix2dos
else
echo "${output}"
fi
} #按逗号分隔字符串,并忽略双引号中的逗号
#逐个字符遍历
#效率贼慢
function dealStr() {
str=$
newStr=""
isOpenQuotes="false"
splitChar="#"
# 遍历字符串的字符
for((i=; i<${#str}; i++))
do
char=${str:$i:}
if [ "$char" == '"' ];then
if [ "$isOpenQuotes" == "false" ];then
isOpenQuotes="true"
else
isOpenQuotes="false"
fi
fi
[ "$char" == "," ] && [ "$isOpenQuotes" == "false" ] && char=${splitChar}
newStr=${newStr}${char}
done
# 按特殊分隔符分割、排序
echo "${newStr}" | awk -F '#' '{for(n=1;n<=NF;n++) print " "$n","}' | sort
} #按逗号分隔字符串,并忽略双引号中的逗号
#遍历字符串中的双引号和逗号
#效率快了一点点
function dealStrTest() {
str=$
newStr=""
isOpenQuotes="false"
splitChar="#" while true
do
indexOfQuotes=`expr index $str '"'`
indexOfComma=`expr index $str ','`
# 处理引号
if [ $indexOfQuotes -gt ] && [ $indexOfComma -gt ] && [ $indexOfQuotes -lt $indexOfComma ];then
if [ "$isOpenQuotes" == "false" ];then
isOpenQuotes="true"
else
isOpenQuotes="false"
fi
newStr=${newStr}${str::$indexOfQuotes}
str=${str:$indexOfQuotes}
# 处理逗号
elif [ $indexOfQuotes -gt ] && [ $indexOfComma -gt ] && [ $indexOfComma -lt $indexOfQuotes ] || [ $indexOfQuotes -eq ] && [ $indexOfComma -gt ];then
[ "$isOpenQuotes" == "false" ] && newStr=${newStr}${str::$indexOfComma-}${splitChar}
[ "$isOpenQuotes" != "false" ] && newStr=${newStr}${str::$indexOfComma}
str=${str:$indexOfComma}
# 逗号没了
elif [ $indexOfComma -eq ];then
newStr=${newStr}${str}
break
else
break
fi
done
# 按特殊分隔符分割、排序
echo "${newStr}" | awk -F '#' '{for(n=1;n<=NF;n++) print " "$n","}' | sort
} #按逗号分隔字符串,并忽略双引号中的逗号
#使用python逐个字符遍历
#效率更快了
function dealStrByPython() {
str=$
newStr=`python -c "
str='$str'
isOpenQuotes=False
splitChar='#'
chArr=[]
for ch in str.replace(' ',''):
if ch == '\"' :
isOpenQuotes = bool(-isOpenQuotes)
if ch == ',' and isOpenQuotes == False :
chArr.append(splitChar)
else :
chArr.append(ch)
print(''.join(chArr))
"`
# 按特殊分隔符分割、排序
echo "${newStr}" | awk -F '#' '{for(n=1;n<=NF;n++) print " "$n","}' | sort
} main $@

(java方式)

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Properties; public class ManifestFormatter { private final static String IMPORT_PACKAGE = "Import-Package";
private final static String EXPORT_PACKAGE = "Export-Package";
private final static char SEPARATOR = '#'; public static void main(String[] args) {
File mf = new File(args[0]);
File formatMf = new File(mf.getParentFile(), "MANIFEST.MF.FORMAT");
if (!mf.exists()) {
System.out.println(mf.getAbsolutePath() + " is format failed: " + mf.getAbsolutePath() + " is not exits");
System.exit(2);
}
try (BufferedReader br = new BufferedReader(new FileReader(mf)); BufferedWriter bw = new BufferedWriter(new FileWriter(formatMf));) {
StringBuilder fileToString = new StringBuilder();
char[] chars = new char[1024];
int len;
while ((len = br.read(chars, 0, chars.length)) != -1) {
fileToString.append(new String(chars, 0, len));
} // 转换MANIFEST.MF文件中的属性为单行模式,并保持原来的文档格式
String lineSeparator = fileToString.indexOf("\r\n") != -1 ? "\r\n" : "\n";
String formatStr = fileToString.toString().replaceAll(lineSeparator + " ", "");
ByteArrayInputStream bi = new ByteArrayInputStream(formatStr.getBytes());
Properties properties = new Properties();
properties.load(bi); // 回写MANIFEST.MF文件,重新写入Import-Package与Export-Package
String importPackageStr = properties.getProperty(IMPORT_PACKAGE);
if (importPackageStr != null && importPackageStr.length() > 0) {
List<String> importPackageList = getPackageList(importPackageStr);
String newImportPackageStr = createNewPackage(importPackageList, IMPORT_PACKAGE, lineSeparator);
formatStr = formatStr.replaceAll("Import-Package:.*" + lineSeparator, newImportPackageStr);
}
String exportPackageStr = properties.getProperty(EXPORT_PACKAGE);
if (exportPackageStr != null && exportPackageStr.length() > 0) {
List<String> exportPackageList = getPackageList(exportPackageStr);
String newExportPackageStr = createNewPackage(exportPackageList, EXPORT_PACKAGE, lineSeparator);
formatStr = formatStr.replaceAll("Export-Package:.*" + lineSeparator, newExportPackageStr);
}
bw.write(formatStr);
} catch (IOException e) {
System.out.println(mf.getAbsolutePath() + " is format failed: " + e.getMessage());
e.printStackTrace();
System.exit(1);
}
System.out.println(mf.getAbsolutePath() + " is format successed");
} /**
* 重新创建Import-Package与Export-Package
*
* @param packageList
* @param packageType
* @param lineSeparator
* @return
*/
private static String createNewPackage(List<String> packageList, String packageType, String lineSeparator) {
StringBuilder newPackageString = new StringBuilder(packageType).append(":").append(lineSeparator);
int size = packageList.size();
for (int i = 0; i < size; i++) {
newPackageString.append(" ");
newPackageString.append(packageList.get(i));
if (i < size - 1) {
newPackageString.append(",");
}
newPackageString.append(lineSeparator);
}
return newPackageString.toString();
} /**
* 单行的Import-Package或Export-Package,转化为list数组
*
* @param packageStr 单行的Import-Package或Export-Package
* @param packageType "Import-Package"或"Export-Package"
* @return
*/
private static List<String> getPackageList(String packageStr) {
boolean isOpenQuotes = false;
char[] chArr = packageStr.replaceAll(" ", "").toCharArray();
int len = chArr.length;
// 双引号外面的逗号,转为分隔符
for (int i = 0; i < len; i++) {
if (chArr[i] == '"') {
isOpenQuotes = !isOpenQuotes;
}
if (chArr[i] == ',' && !isOpenQuotes) {
chArr[i] = SEPARATOR;
}
}
List<String> packageList = Arrays.asList(new String(chArr).split(SEPARATOR + ""));
Collections.sort(packageList);
return packageList;
} }

MANIFEST.MF文件对Import-Package/Export-Package重排列的更多相关文章

  1. 关于java中的MANIFEST.MF 文件内容

    打开Java的JAR文件我们经常可以看到文件中包含着一个META-INF目录, 这个目录下会有一些文件,其中必有一个MANIFEST.MF,这个文件描述了该Jar文件的很多信息.可以简化Java应用程 ...

  2. Jar文件 META-INF/MANIFEST.MF文件详解

    打开Java的JAR文件我们经常可以看到文件中包含着一个META-INF目录, 这个目录下会有一些文件,其中必有一个MANIFEST.MF,这个文件描述了该Jar文件的很多信息,下面将详细介绍MANI ...

  3. meta-inf文件夹以及MANIFEST.MF文件的作用

    meta-inf相当于一个信息包,目录中的文件和目录获得Java 2平台的认可与解释,用来配置应用程序.扩展程序.类加载器和服务 manifest.mf文件,在用jar打包时自动生成的. META-I ...

  4. MANIFEST.MF文件Class-Path:节点需要引入的jar太多解决方案

    每行开头结尾都要有一个空格(半角的) 例子如下: Manifest-Version: 1.0 Class-Path: lib/mongo-java-driver-2.11.4.jar lib/guav ...

  5. JAR包中的MANIFEST.MF文件详解以及编写规范

    参考百度百科的解释如下: http://baike.baidu.com/item/MANIFEST.MF MANIFEST.MF:这个 manifest 文件定义了与扩展和包相关的数据.单词“mani ...

  6. MANIFEST.MF 文件内容完全详解(转)

    打开Java的JAR文件我们经常可以看到文件中包含着一个META-INF目录, 这个目录下会有一些文件,其中必有一个MANIFEST.MF,这个文件描述了该Jar文件的很多信息,下面将详细介绍MANI ...

  7. MANIFEST.MF Error: No available bundle exports package

    Issue: When you imported some 3rd jars and compiled MANIFEST.MF, you may got following compling erro ...

  8. jar包的MANIFEST.MF文件

    打包可执行jar包时,MANIFEST.MF总是个让人头疼的东西,经常出现这种那种问题. 一个例子: ================================================= ...

  9. JAR包结构,META-INF/MANIFEST.MF文件详细说明[全部属性][打包][JDK]

    转载请注:[https://www.cnblogs.com/applerosa/p/9736729.html] 常见的属性 jar文件的用途 压缩的和未压缩的 jar工具 可执行的JAR 1.创建可执 ...

随机推荐

  1. Ognl 使用实例手册

    上一篇博文介绍了ongl的基础语法,接下来进入实际的使用篇,我们将结合一些实际的case,来演示ognl究竟可以支撑到什么地步 在看本文之前,强烈建议先熟悉一下什么是ognl,以及其语法特点,减少阅读 ...

  2. 连上Microbit板

    我们是在自己电脑上,用Mu编程,最终程序要烧录到Microbi板子的控制芯片中去,还记得这款芯片是哪家公司生产的?是多少位的?呵呵. 因此,我们要把板子和电脑连起来,用常见的一大一小的USB线就可以了 ...

  3. Mysql系列(三)—— Mysql主从复制配置

    一.前言 主从复制是Mysql知识体系中非常重的要一个模块.学习主从复制和后续的读写分离是完善只是知识体系的重要环节.且主从复制读写分离的思想并不仅仅局限于Mysql,在很多存储系统中都有该方案,如: ...

  4. 《JavaEE开发的颠覆者——Spring Boot实战》是一本好书

    这本书的风格非常好.每一节都是先点明这一块知识的要点,随后就手把手的做出一个最简明.但有能体现核心的实例(大多只有几个Class) 这样的书用来熟悉一门框架,实在是再好不过.

  5. Map作为缓存使用

    public class MapCache { /** * 默认存储1024个缓存 */ private static final int DEFAULT_CACHES = 1024; private ...

  6. jQuery---jQ动画(普通,滑动,淡入淡出,自定义动画,停止动画),jQuery的事件,jQ事件的绑定/解绑,一次性事件,事件委托,事件冒泡,文档加载

    jQuery---jQ动画(普通,滑动,淡入淡出,自定义动画,停止动画),jQuery的事件,jQ事件的绑定/解绑,一次性事件,事件委托,事件冒泡,文档加载 一丶jQuery动画 show,hide, ...

  7. python基础知识(一)

    Python基础知识 计算基础知识 1.cpu 人类的大脑 运算和处理问题 2.内存 临时存储数据 断电就消失了 3.硬盘 永久存储数据 4.操作系统 调度硬件设备之间数据交互 python的应用和历 ...

  8. Springboot 基于的SAP项目环境配置

    做SAP开发,感觉最难的莫过于前期的环境了,也就是说让程序能跑起来.. 最重要的有三个文件(较新版本,jco lib版本721.800) 下载libsapjco3.so.sapjco3.dll.sap ...

  9. 学习笔记之Python 3

    学习笔记之Python 3 教程 https://www.cnblogs.com/pegasus923/p/7624416.html 学习笔记之X分钟速成Python3 https://www.cnb ...

  10. 组件切换方式(Vue.js)

    这里,我用一个注册登录两组件的切换实例来演示: 切换方式一 <!DOCTYPE html> <html lang="zh-CN"> <head> ...