MANIFEST.MF文件对Import-Package/Export-Package重排列
众所周知,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重排列的更多相关文章
- 关于java中的MANIFEST.MF 文件内容
打开Java的JAR文件我们经常可以看到文件中包含着一个META-INF目录, 这个目录下会有一些文件,其中必有一个MANIFEST.MF,这个文件描述了该Jar文件的很多信息.可以简化Java应用程 ...
- Jar文件 META-INF/MANIFEST.MF文件详解
打开Java的JAR文件我们经常可以看到文件中包含着一个META-INF目录, 这个目录下会有一些文件,其中必有一个MANIFEST.MF,这个文件描述了该Jar文件的很多信息,下面将详细介绍MANI ...
- meta-inf文件夹以及MANIFEST.MF文件的作用
meta-inf相当于一个信息包,目录中的文件和目录获得Java 2平台的认可与解释,用来配置应用程序.扩展程序.类加载器和服务 manifest.mf文件,在用jar打包时自动生成的. META-I ...
- MANIFEST.MF文件Class-Path:节点需要引入的jar太多解决方案
每行开头结尾都要有一个空格(半角的) 例子如下: Manifest-Version: 1.0 Class-Path: lib/mongo-java-driver-2.11.4.jar lib/guav ...
- JAR包中的MANIFEST.MF文件详解以及编写规范
参考百度百科的解释如下: http://baike.baidu.com/item/MANIFEST.MF MANIFEST.MF:这个 manifest 文件定义了与扩展和包相关的数据.单词“mani ...
- MANIFEST.MF 文件内容完全详解(转)
打开Java的JAR文件我们经常可以看到文件中包含着一个META-INF目录, 这个目录下会有一些文件,其中必有一个MANIFEST.MF,这个文件描述了该Jar文件的很多信息,下面将详细介绍MANI ...
- 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 ...
- jar包的MANIFEST.MF文件
打包可执行jar包时,MANIFEST.MF总是个让人头疼的东西,经常出现这种那种问题. 一个例子: ================================================= ...
- JAR包结构,META-INF/MANIFEST.MF文件详细说明[全部属性][打包][JDK]
转载请注:[https://www.cnblogs.com/applerosa/p/9736729.html] 常见的属性 jar文件的用途 压缩的和未压缩的 jar工具 可执行的JAR 1.创建可执 ...
随机推荐
- element-ui 开发备忘
目录 购物清单的数据结构说明 1. <el-radio> 的 label 属性 2. 在 <el-table> 中放入表单组件 3. 表单验证时填写正确的 prop 属性 总结 ...
- CountDownLatch源码
public class CountDownLatchExample1 { public static void main(String[] args) throws Exception { Exec ...
- Xamarin.Android DatePickerFragment 日期控件
MainActivity 代码: public class MainActivity : Activity { TextView _dateDisplay; Button _dateSelectBut ...
- [转帖]java注解核心知识总结
java注解核心知识总结 2019-11-01 20:39:50 从事Java 阅读数 2 收藏 文章标签: java注解总结程序员 更多 分类专栏: java 注解 版权声明:本文为博主原创文 ...
- 【转帖】Linux文件夹对比并提取的差分文件技巧-rsync的妙用
Linux文件夹对比并提取的差分文件技巧-rsync的妙用 [日期:2016-02-13] 来源:oschina.net 作者:mengshuai [字体:大 中 小] https://www.li ...
- Java使用正则表达式匹配多行 Pattern flags
Java中正则匹配有多种模式,若不选择模式则默认为单行匹配 匹配模式(Pattern flags) compile()方法有两个模式 未开匹配模式 Pattern compile(String reg ...
- Java 8 HashMap 源码解析
HashMap 使用数组.链表和红黑树存储键值对,当链表足够长时,会转换为红黑树.HashMap 是非线程安全的. HashMap 中的常量 static final int DEFAULT_INIT ...
- java自定义异常和throw、throws的使用
一.自定义异常类 我们知道所有的异常都是Exception,所以我们需要自定义异常只需要继承那个Exception类就可以了.下面我们自定义一个异常类,代码如下: /** * 自定义异常, */ // ...
- SSRS连接ORACLE数据库制作报表
SSRS报表基于ORACLE数据库做报表示例. 开发环境:VS2010 SQL SERVER 数据库:SQL SERVER 2012 PS:数据库连接部分可能有还有个问题就是ORACLE数据源这一部分 ...
- Mybatis源码解析(三) —— Mapper代理类的生成
Mybatis源码解析(三) -- Mapper代理类的生成 在本系列第一篇文章已经讲述过在Mybatis-Spring项目中,是通过 MapperFactoryBean 的 getObject( ...