如何转换清单 <Integer> Java中的int []? [重复]

本文探讨了在Java中如何高效地将List&lt;Integer&gt;转换为int[]数组,提供了多种方法,包括使用循环、lambda表达式、Java 8的Stream API以及第三方库如Guava和Apache Commons Lang。

本文翻译自:How to convert List to int[] in Java? [duplicate]

This question already has an answer here: 这个问题已经在这里有了答案:

This is similar to this question: How to convert int[] to Integer[] in Java? 这类似于以下问题: 如何在Java中将int []转换为Integer []?

I'm new to Java. 我是Java新手。 How can i convert a List<Integer> to int[] in Java? 如何在Java中将List<Integer>转换为int[] I'm confused because List.toArray() actually returns an Object[] , which can be cast to nether Integer[] or int[] . 我很困惑,因为List.toArray()实际上返回一个Object[] ,可以将其List.toArray()Integer[]int[]

Right now I'm using a loop to do so: 现在,我正在使用循环来做到这一点:

int[] toIntArray(List<Integer> list){
  int[] ret = new int[list.size()];
  for(int i = 0;i < ret.length;i++)
    ret[i] = list.get(i);
  return ret;
}

I'm sure there's a better way to do this. 我敢肯定有更好的方法可以做到这一点。


#1楼

参考:https://stackoom.com/question/41qp/如何转换清单-Integer-Java中的int-重复


#2楼

Using a lambda you could do this (compiles in jdk lambda): 使用lambda可以做到这一点(在jdk lambda中编译):

public static void main(String ars[]) {
        TransformService transformService = (inputs) -> {
            int[] ints = new int[inputs.size()];
            int i = 0;
            for (Integer element : inputs) {
                ints[ i++ ] = element;
            }
            return ints;
        };

        List<Integer> inputs = new ArrayList<Integer>(5) { {add(10); add(10);} };

        int[] results = transformService.transform(inputs);
    }

    public interface TransformService {
        int[] transform(List<Integer> inputs);
    }

#3楼

I'll throw one more in here. 我还要再扔一个。 I've noticed several uses of for loops, but you don't even need anything inside the loop. 我注意到for循环的几种用法,但是您甚至在循环内都不需要任何东西。 I mention this only because the original question was trying to find less verbose code. 我之所以提及这一点,仅是因为最初的问题是试图找到较少的冗长代码。

int[] toArray(List<Integer> list) {
    int[] ret = new int[ list.size() ];
    int i = 0;
    for( Iterator<Integer> it = list.iterator(); 
         it.hasNext(); 
         ret[i++] = it.next() );
    return ret;
}

If Java allowed multiple declarations in a for loop the way C++ does, we could go a step further and do for(int i = 0, Iterator it... 如果Java像C ++一样在for循环中允许多个声明,我们可以进一步做for(int i = 0,Iterator it ...

In the end though (this part is just my opinion), if you are going to have a helping function or method to do something for you, just set it up and forget about it. 最后,(这只是我的观点),如果您要使用帮助功能或方法来为您做某事,则只需进行设置,然后再进行操作即可。 It can be a one-liner or ten; 它可以是一排或十排; if you'll never look at it again you won't know the difference. 如果您再也不会看它,您将不会知道其中的区别。


#4楼

No one mentioned yet streams added in Java 8 so here it goes: 到目前为止,还没有人提到Java 8中添加了流。

int[] array = list.stream().mapToInt(i->i).toArray();

Thought process: 思考过程:

  • simple Stream#toArray returns Object[] , so it is not what we want. 简单的Stream#toArray返回Object[] ,所以这不是我们想要的。 Also Stream#toArray(IntFunction<A[]> generator) doesn't do what we want because generic type A can't represent primitive int 另外Stream#toArray(IntFunction<A[]> generator)不能满足我们的要求,因为通用类型A无法表示原始int
  • so it would be nice to have some stream which could handle primitive type int instead of wrapper Integer , because its toArray method will most likely also return int[] array (returning something else like Object[] or even boxed Integer[] would be unnatural here). 因此,最好有一些可以处理原始类型int而不是包装器Integer ,因为它的toArray方法很可能还会返回int[]数组(返回诸如Object[]或装箱的Integer[]类的其他东西是不自然的这里)。 And fortunately Java 8 has such stream which is IntStream 幸运的是,Java 8具有这样的流,即IntStream
  • so now only thing we need to figure out is how to convert our Stream<Integer> (which will be returned from list.stream() ) to that shiny IntStream . 所以现在我们唯一需要弄清楚的是如何将Stream<Integer> (将从list.stream()返回)转换为该闪亮的IntStream Here Stream#mapToInt(ToIntFunction<? super T> mapper) method comes to a rescue. 这里Stream#mapToInt(ToIntFunction<? super T> mapper)方法可以解决。 All we need to do is pass to it mapping from Integer to int . 我们需要做的就是将它从Integer映射到int We could use something like Integer#getValue which returns int like : 我们可以使用类似Integer#getValue东西,它返回int像这样:

     mapToInt( (Integer i) -> i.intValue() ) 

    (or if someone prefers mapToInt(Integer::intValue) ) (或者如果有人喜欢mapToInt(Integer::intValue)

    but similar code can be generated using unboxing, since compiler knows that result of this lambda must be int (lambda in mapToInt is implementation of ToIntFunction interface which expects body for int applyAsInt(T value) method which is expected to return int ). 但是可以使用拆箱生成类似的代码,因为编译器知道此lambda的结果必须为intmapToInt中的mapToIntToIntFunction接口的实现, ToIntFunction接口期望int applyAsInt(T value)主体int applyAsInt(T value)方法,该方法应返回int )。

    So we can simply write 所以我们可以简单地写

     mapToInt((Integer i)->i) 

    Also since Integer type in (Integer i) can be inferred by compiler because List<Integer>#stream() returns Stream<Integer> we can also skip it which leaves us with 同样由于编译器可以推断(Integer i) Integer类型,因为List<Integer>#stream()返回Stream<Integer>我们也可以跳过它,从而使我们

     mapToInt(i -> i) 

#5楼

In addition to Commons Lang, you can do this with Guava 's method Ints.toArray(Collection<Integer> collection) : 除了Ints.toArray(Collection<Integer> collection) Lang之外,您还可以使用GuavaInts.toArray(Collection<Integer> collection)

List<Integer> list = ...
int[] ints = Ints.toArray(list);

This saves you having to do the intermediate array conversion that the Commons Lang equivalent requires yourself. 这样就省去了Commons Lang等效项需要自己进行的中间数组转换的麻烦。


#6楼

try also Dollar ( check this revision ): 也可以尝试Dollars检查此修订版 ):

import static com.humaorie.dollar.Dollar.*
...

List<Integer> source = ...;
int[] ints = $(source).convert().toIntArray();
com.alipay.easysdk.factory.Payment.Page() orderMapper.updatePayStatus(outTradeNo, alipayTradeNo, new Date(), 2);这个报错和xml文件有关吗<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <!--父工程依赖 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.5</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.pyk</groupId> <artifactId>1</artifactId> <version>0.0.1-SNAPSHOT</version> <name>cloud_class_gitee</name> <description>cloud_class_gitee</description> <url/> <licenses> <license/> </licenses> <developers> <developer/> </developers> <scm> <connection/> <developerConnection/> <tag/> <url/> </scm> <properties> <java.version>17</java.version> <maven.exam.skip>true</maven.exam.skip> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.2</version> </dependency> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <!-- 单元测试依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter-test</artifactId> <version>2.2.2</version> <scope>test</scope> </dependency> <!-- lombok依赖--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> </dependency> <!-- validation依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <!--java-jwt依赖 --> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>4.4.0</version> </dependency> <!--pagehelper 工具 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.4.6</version> </dependency> <!-- MinIO Java SDK --> <dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>8.3.4</version> </dependency> <!-- swagger Api 接口 --> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>3.0.2</version> </dependency> <!--redis依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- excel导入导出--> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.0.5</version> </dependency> <dependency> <groupId>org.burningwave</groupId> <artifactId>core</artifactId> <version>9.5.2</version> </dependency> <!--上传文件--> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>3.1.0</version> <!-- 使用最新版本 --> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.76</version> </dependency> <!--集合工具类--> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.16</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> <!-- 切面编程 登录操作日志--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <!--登录验证码--> <dependency> <groupId>com.github.whvcse</groupId> <artifactId>easy-captcha</artifactId> <version>1.6.2</version> </dependency> <!--okhttp3--> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.9.1</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>3.4.4</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.2</version> <!-- 确保版本一致 --> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.15.2</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.15.2</version> </dependency> <!-- 支付宝依赖沙箱支付 --> <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-easysdk</artifactId> <version>2.2.0</version> </dependency> <!-- 支付宝相关--> <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>4.34.0.ALL</version> </dependency> <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-easysdk</artifactId> <version>2.2.0</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.0.0-M5</version> <configuration> <argLine>--add-opens java.base/java.lang=ALL-UNNAMED</argLine> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
11-06
package com.kucun; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; @SpringBootApplication( ) public class DemoApplication extends SpringBootServletInitializer { public static void main(String[] args) { // // ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args); // Arrays.stream(ctx.getBeanNamesForType(SecurityFilterChain.class)) // .forEach(System.out::println); // // // // 测试密码加密示例 // BCryptPasswordEncoder encoder = new BCrypt(); // String rawPassword = "987987"; // String encodedPassword = encoder.encode(rawPassword); // System.out.println("加密后的密码:" + encodedPassword); SpringApplication.run(DemoApplication.class, args); } }<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>KuCun2</groupId> <artifactId>KuCun2</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <name>KuCun2</name> <description/> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.12.RELEASE</version> <!-- 请根据需要选择版本 --> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <webVersion>4.0</webVersion> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <protobuf.version>3.21.12</protobuf.version> </properties> <dependencies> <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>8.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.glassfish.web</groupId> <artifactId>javax.servlet.jsp.jstl</artifactId> <version>1.2.4</version> </dependency> <!-- Spring Boot Starter Data JPA --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- MySQL Connector --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> <exclusions> <exclusion> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> </exclusion> </exclusions> </dependency> <!-- Optional: Lombok for reducing boilerplate code --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> </dependency> <!-- Jackson Databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <!-- Jackson Core --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> </dependency> <!-- Jackson Annotations --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> </dependency> <dependency> <groupId>org.mindrot</groupId> <artifactId>jbcrypt</artifactId> <version>0.4</version> </dependency> <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>${protobuf.version}</version> </dependency> <dependency> <groupId>org.yaml</groupId> <artifactId>snakeyaml</artifactId> <version>1.30</version> <!-- 统一版本号 --> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.8</source> <target>1.8</target> <compilerArgs> <arg>-parameters</arg> </compilerArgs> </configuration> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>2.6</version> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> </plugins> </build> </project> package com.kucun.Config.user; import java.util.Collection; import com.kucun.data.entity.User; public class CustomUserDetails /*implements UserDetails*/ { // /** // * // */ // private static final long serialVersionUID = 1L; // private final String andy; // 对应andy字段 // private final String name; // private final int role; // private final String password; // private final User users; // private final Collection<? extends GrantedAuthority> authorities; // // public CustomUserDetails(User user, Collection<? extends GrantedAuthority> authorities) { // this.andy = user.getAndy(); // this.name = user.getName(); // this.role = user.getRole(); // this.password = user.getPass(); // user.setPass(null); // this.users=user; // this.authorities = authorities; // } // // // 实现UserDetails接口方法 // @Override public String getUsername() { return andy; } // @Override public String getPassword() { return password; } // @Override public Collection<? extends GrantedAuthority> getAuthorities() { return authorities; } // // // 自定义字段访问方法 // public String getName() { return name; } // public User getUser() { return users; } // public int getRole() { return role; } // // // 其他必要方法 // @Override public boolean isAccountNonExpired() { return true; } // @Override public boolean isAccountNonLocked() { return true; } // @Override public boolean isCredentialsNonExpired() { return true; } // @Override public boolean isEnabled() { return true; } }package com.kucun.Config.Role; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.annotation.PostConstruct; import javax.json.Json; import org.springframework.stereotype.Component; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; /** * 权限转化 * @author Administrator * */ @Component public class RoleConverter { // private static final Map<Integer, String> ROLE_MAP = new HashMap<>(); // // @PostConstruct // public void init() { // ROLE_MAP.put(0, "ROLE_ADMIN"); // ROLE_MAP.put(1, "ROLE_USER"); // ROLE_MAP.put(2, "ROLE_MANAGER"); // ROLE_MAP.put(3, "ROLE_AUDITOR"); // } // // public List<GrantedAuthority> convert(int roleCode) { // ObjectMapper mapper = new ObjectMapper(); // try { // System.out.println(mapper.writeValueAsString(Collections.singletonList( // new SimpleGrantedAuthority(ROLE_MAP.getOrDefault(roleCode, "ROLE_GUEST")))).toString());//输出[{"authority":"ROLE_ADMIN"}] // } catch (JsonProcessingException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } // // return Collections.singletonList( // new SimpleGrantedAuthority(ROLE_MAP.getOrDefault(roleCode, "ROLE_GUEST")) // ); // } // }package com.kucun.Config; // 2. 基础安全配置 //@Configuration //@EnableWebSecurity // 启用Web安全功能 public class SecurityConfig //extends WebSecurityConfigurerAdapter { // @Override // public void configure(WebSecurity web) { // web.ignoring().antMatchers("/check-session"); // } // // 添加自定义Controller // @RestController // public static class SessionCheckController { // @GetMapping("/check-session") // public ResponseEntity<?> checkSession(HttpServletRequest request) { // return request.getSession(false) != null ? // ResponseEntity.ok().build() : // ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); // } // } // /** // * 核心安全过滤器链配置 // * @param http HTTP安全构建器 // * @return 安全过滤器链 // * @throws Exception 配置异常 // * // * █ 配置逻辑说明: // * 1. authorizeHttpRequests: 定义访问控制规则 // * 2. formLogin: 配置表单登录 // * 3. logout: 配置注销行为 // * 4. exceptionHandling: 处理权限异常[^3] // */ // // // 修正后的配置方法 // @Override // protected void configure(HttpSecurity http) throws Exception { // // // // http // .csrf().disable() // .sessionManagement() // .sessionCreationPolicy(SessionCreationPolicy.ALWAYS) // .invalidSessionUrl("/login.html?session=invalid") // .maximumSessions(1) // .maxSessionsPreventsLogin(false) // .and() // .and() // .addFilterBefore(jsonAuthFilter(), UsernamePasswordAuthenticationFilter.class) // 关键配置 // .authorizeRequests() // .antMatchers("/login.html", "/users/login").permitAll() // .antMatchers("/js/**", "/css/**", "/fonts/**", "/images/**","/check-session","/main/bootstrap-3.3.7-dist/**").permitAll() // .antMatchers("/users/guanli/**").hasAuthority("ROLE_ADMIN") // .anyRequest().authenticated() // .and() // .formLogin().disable() //// .loginPage("/login.html") //// .loginProcessingUrl("/users/login") //// //// .successHandler(ajaxAuthenticationSuccessHandler()) // 自定义成功处理器 //// .failureHandler(ajaxAuthenticationFailureHandler()) // 自定义失败处理器 //// .defaultSuccessUrl("/index.html") //// .failureUrl("/login.html?error=true") //// .usernameParameter("andy") // 修改用户名参数名 //// .passwordParameter("pass") // 修改密码参数名 //// .and() // // .logout() // .logoutUrl("/logout") // .logoutSuccessUrl("/login.html") // .and() // .csrf() // .ignoringAntMatchers("/users/login") // .and() // .headers() // .frameOptions().sameOrigin() // .and() // .exceptionHandling() // .accessDeniedHandler(accessDeniedHandler()); // 统一使用Handler // } // // // // // // // 返回JSON格式的成功响应 // @Bean // public AuthenticationSuccessHandler ajaxAuthenticationSuccessHandler() { // return (request, response, authentication) -> { // // // // // 强制创建服务端会话 // request.getSession(true); // // // // // String contextPath = request.getContextPath(); // HttpSession session = request.getSession(true); // Cookie cookie = new Cookie("JSESSIONID", session.getId()); // cookie.setPath(contextPath.isEmpty() ? "/" : contextPath + "/"); // cookie.setMaxAge(1800); // 30分钟 // response.addCookie(cookie); // // // //构建安全响应数据 // Map<String, Object> responseData = new HashMap<>(); // responseData.put("sessionId", request.getSession().getId()); // responseData.put("userInfo",Collections.unmodifiableMap(new HashMap<String, Object>() {/** // * // */ // private static final long serialVersionUID = 1L; // // { // put("Name", ((CustomUserDetails)authentication.getPrincipal()).getName()); // put("role", ((CustomUserDetails)authentication.getPrincipal()).getRole()); // }})); // // // // // 统一返回JSON格式 // response.setContentType(MediaType.APPLICATION_JSON_VALUE); // // new ObjectMapper().writeValue(response.getWriter(), responseData); // // // // // // // // // // response.setContentType(MediaType.APPLICATION_JSON_VALUE); // CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal(); // // response.setStatus(HttpStatus.OK.value()); // System.out.println(authentication.getPrincipal()+""+authentication.getName()); // // if (request.getHeader("X-Requested-With") == null) { // 非AJAX请求 // response.sendRedirect("/index.html"); // } else { // // //String re=userDetails.getUser().toString() // new ObjectMapper().writeValue(response.getWriter(), userDetails.getUser() // ); // // } // // // // // // // }; // } // // // 返回401状态码和错误信息 // @Bean // public AuthenticationFailureHandler ajaxAuthenticationFailureHandler() { // return (request, response, exception) -> { // if (request.getHeader("X-Requested-With") == null) { // response.sendRedirect("/login.html?error=true"); // } else { // response.setStatus(HttpStatus.UNAUTHORIZED.value()); // response.getWriter().write("{\"error\":\"Authentication failed\"}"); // } // }; // } // // // 处理未认证请求 // @Bean // public AuthenticationEntryPoint ajaxAuthenticationEntryPoint() { // return (request, response, exception) -> { // if (request.getHeader("X-Requested-With") == null) { // response.sendRedirect("/login.html?error=true"); // } else { // response.setStatus(HttpStatus.UNAUTHORIZED.value()); // response.getWriter().write("{\"error\":\"Authentication failed\"}"); // } // }; // } // // // // // // @Bean // public JsonUsernamePasswordAuthenticationFilter jsonAuthFilter() throws Exception { // // JsonUsernamePasswordAuthenticationFilter filter = // new JsonUsernamePasswordAuthenticationFilter(); // filter.setAuthenticationManager(authenticationManagerBean()); // filter.setUsernameParameter("andy"); // 设置自定义参数名 // filter.setPasswordParameter("pass"); // filter.setFilterProcessesUrl("/users/login"); // filter.setAuthenticationSuccessHandler(ajaxAuthenticationSuccessHandler()); // filter.setAuthenticationFailureHandler(ajaxAuthenticationFailureHandler()); // // return filter; // } // // // /** // * 密码编码器(必须配置) // * 使用BCrypt强哈希算法加密 // */ // @Bean // public PasswordEncoder passwordEncoder() { // return new BCryptPasswordEncoder(); // } // // // @Bean // public AccessDeniedHandler accessDeniedHandler() { // System.out.println("0000"); // return (request, response, ex) -> { // if (!response.isCommitted()) { // response.sendRedirect("/error/403"); // } // }; // } // // //} // // // // // // //class JsonUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter { // private final ObjectMapper objectMapper = new ObjectMapper(); // // @Override // public Authentication attemptAuthentication(HttpServletRequest request, // HttpServletResponse response) // throws AuthenticationException { // System.out.println("收到认证请求,路径:" + request.getRequestURI()); // System.out.println("请求方法:" + request.getMethod()); // System.out.println("Content-Type:" + request.getContentType()); // if (request.getContentType() != null && // request.getContentType().startsWith(MediaType.APPLICATION_JSON_VALUE)) { // // try (InputStream is = request.getInputStream()) { // Map<String, String> authMap = objectMapper.readValue(is, Map.class); // // String username = authMap.getOrDefault(getUsernameParameter(), ""); // String password = authMap.getOrDefault(getPasswordParameter(), ""); // // // 调试日志 // System.out.println("Authentication attempt with: " + username+'_'+ password); // // UsernamePasswordAuthenticationToken authRequest = // new UsernamePasswordAuthenticationToken(username, password); // // setDetails(request, authRequest); // return this.getAuthenticationManager().authenticate(authRequest); // } catch (IOException e) { // throw new AuthenticationServiceException("认证请求解析失败", e); // } // } // Authentication aut= super.attemptAuthentication(request, response); // System.out.println("结果:"+aut.isAuthenticated()); // // return aut; // } } package com.kucun.Config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.kucun.Config.Role.RoleConverter; import com.kucun.Config.user.CustomUserDetails; import com.kucun.data.entity.User; import com.kucun.dataDo.UserRepository; /** * 获取数据 * @author Administrator * */ @Service public class CustomUserDetailsService/* implements UserDetailsService */{ // // @Autowired // private UserRepository userRepository; // // @Autowired // private RoleConverter roleConverter; // // public CustomUserDetailsService() { // // super(); // System.out.println("11111"); // } ///** // * 获取数据库中用户信息 // * @param andy 账号 // * // * @return // * // */ // @Override // public UserDetails loadUserByUsername(String andy) { // System.out.println(andy); // User user = userRepository.findByAndy(andy); // System.out.println(user); // return new CustomUserDetails(user, // roleConverter.convert(user.getRole()) // 关键转换点[^1] // ); // } } 不加安全类的情况下解决重定向问题 }
06-01
实体类 Category.java Java @Data public class Category { private Integer id; private String title; private Integer parentId; private Integer sort; private List<Category> children; } Mapper 接口 CategoryMapper.java Java @Mapper public interface CategoryMapper { // 查询所有分类(平铺结构) @Select("SELECT id, title, parent_id as parentId, sort FROM category ORDER BY sort DESC") List<Category> selectAll(); // 递归查询树形结构(MyBatis的嵌套结果映射) @Select("SELECT id, title, parent_id as parentId, sort FROM category") @Results({ @Result(property = "id", column = "id"), @Result(property = "children", column = "id", many = @Many(select = "findByParentId")) }) List<Category> selectTree(); @Select("SELECT id, title, parent_id as parentId, sort FROM category WHERE parent_id = #{parentId}") List<Category> findByParentId(Integer parentId); } Service 层 CategoryService.java Java @Service @RequiredArgsConstructor public class CategoryService { private final CategoryMapper categoryMapper; public Result getCategoryTree() { List<Category> categories = categoryMapper.selectTree(); return Result.success(categories); } // 备选方案:Java递归构建树 public List<Category> buildTree(List<Category> allNodes) { List<Category> rootNodes = allNodes.stream() .filter(n -> n.getParentId() == null) .sorted(Comparator.comparing(Category::getSort).reversed()) .collect(Collectors.toList()); rootNodes.forEach(n -> findChildren(n, allNodes)); return rootNodes; } private void findChildren(Category parent, List<Category> allNodes) { List<Category> children = allNodes.stream() .filter(n -> parent.getId().equals(n.getParentId())) .sorted(Comparator.comparing(Category::getSort).reversed()) .collect(Collectors.toList()); parent.setChildren(children); children.forEach(child -> findChildren(child, allNodes)); } } Controller 层 CategoryController.java Java @RestController @RequestMapping("/api/category") @RequiredArgsConstructor public class CategoryController { private final CategoryService categoryService; @GetMapping("/tree") public Result getTree() { return categoryService.getCategoryTree(); } }加上之后idea报Error starting ApplicationContext. To display the condition evaluation report re-run your application with ‘debug’ enabled. 2025-03-20T21:06:10.275+08:00 ERROR 12884 — [ main] o.s.boot.SpringApplication : Application run failed
03-21
import java.io.ByteArrayOutputStream; import java.net.*; import java.util.*; /** * UdpTsInspector * 监听 UDP 组播 TS,解析 PAT/PMT/SDT,节目号/节目名/各节目流速率统计 * JDK 1.6 兼容版 */ public class UdpTsInspector { // ==== 配置 ==== static final String MCAST_IP = "236.78.78.1"; static final int PORT = 59000; static final int MTU = 7 * 188; // UDP 一帧里常见多个 TS 包 // PSI 常量 static final int PID_PAT = 0x0000; static final int PID_SDT = 0x0011; // SDT/BAT static final int PID_NULL = 0x1FFF; // 节目与 PID 的关系 static final Map<Integer, Integer> progToPmtPid = new HashMap<Integer, Integer>(); // program_number -> PMT PID static final Map<Integer, Set<Integer>> programEsPids = new HashMap<Integer, Set<Integer>>(); // program_number -> ES PIDs static final Map<Integer, String> programNames = new HashMap<Integer, String>(); // program_number -> service_name // PID → 节目 的反查(便于统计) static final Map<Integer, Integer> pidToProgram = new HashMap<Integer, Integer>(); // PID 字节计数(用于码率) static final Map<Integer, Long> pidBytesCounter = new HashMap<Integer, Long>(); static long lastReportNs = System.nanoTime(); static final long REPORT_INTERVAL_NS = 3000000000L; // 3s // PSI 重组缓存:一个 PID 里可能会分段 static final Map<Integer, SectionAssembler> assemblers = new HashMap<Integer, SectionAssembler>(); // 每个节目:详细 ES 信息(pid + stream_type + 粗分类 + 友好名) static final Map<Integer, List<EsInfo>> programEsInfo = new HashMap<Integer, List<EsInfo>>(); static class EsInfo { int pid; int streamType; String kind; // "video" / "audio" / "other" String codec; // "H.264/AVC" / "HEVC" / "AAC" / "AC-3" ... EsInfo(int pid, int st, String kind, String codec) { this.pid = pid; this.streamType = st; this.kind = kind; this.codec = codec; } } public static void main(String[] args) throws Exception { System.out.println("Listen UDP multicast: " + MCAST_IP + ":" + PORT); MulticastSocket sock = new MulticastSocket(PORT); try { InetAddress grp = InetAddress.getByName(MCAST_IP); sock.joinGroup(grp); } catch (Throwable t) { System.err.println("Join group failed: " + t); } byte[] buf = new byte[MTU]; DatagramPacket pkt = new DatagramPacket(buf, buf.length); while (true) { sock.receive(pkt); int len = pkt.getLength(); int off = 0; while (off + 188 <= len) { parseTsPacket(buf, off); off += 188; } maybeReport(); } } /* 解析一个 188B TS 包 */ static void parseTsPacket(byte[] b, int off) { if ((b[off] & 0xFF) != 0x47) return; // sync int tei = (b[off+1] & 0x80) >>> 7; int pusi = (b[off+1] & 0x40) >>> 6; int pid = ((b[off+1] & 0x1F) << 8) | (b[off+2] & 0xFF); int afc = (b[off+3] & 0x30) >>> 4; if (tei == 1) return; // 传输错误,丢弃 // 统计:把 TS 包字节计入对应 PID(过滤 null) if (pid != PID_NULL) { Long old = pidBytesCounter.get(pid); pidBytesCounter.put(pid, (old == null ? 0L : old) + 188L); } int i = off + 4; if (afc == 2) return; // 只有 AF,无 payload if (afc == 3) { // 跳过 AF int afl = b[i] & 0xFF; i += 1 + afl; } if (i >= off + 188) return; // 仅处理 PSI(PAT/PMT/SDT)以获取节目/名称 if (pid == PID_PAT || pid == PID_SDT || containsValue(progToPmtPid, pid)) { SectionAssembler sa = assemblers.get(pid); if (sa == null) { sa = new SectionAssembler(); assemblers.put(pid, sa); } sa.push(b, i, off + 188 - i, pusi == 1, (b[off+3] & 0x0F)); // continuity 不做严格校验 while (sa.hasSection()) { byte[] sec = sa.pollSection(); parseSection(pid, sec); } } } // JDK6无Map.containsValue泛型重载,自己写 static boolean containsValue(Map<Integer, Integer> map, int val) { for (Integer v : map.values()) if (v != null && v.intValue() == val) return true; return false; } /* 解析一个 PSI section(含 table_id、section_length 等完整体) */ static void parseSection(int pid, byte[] sec) { if (sec.length < 3) return; int tableId = sec[0] & 0xFF; int sectionLength = ((sec[1] & 0x0F) << 8) | (sec[2] & 0xFF); if (sectionLength + 3 != sec.length) return; // 粗略校验 if (pid == PID_PAT && tableId == 0x00) { parsePAT(sec); } else if (pid == PID_SDT && (tableId == 0x42 || tableId == 0x46)) { parseSDT(sec); } else if (tableId == 0x02) { parsePMT(sec); } } static void parsePAT(byte[] sec) { // 解析PAT头部信息 int sectionSyntaxIndicator = (sec[1] & 0x80) >>> 7; int sectionLength = ((sec[1] & 0x0F) << 8) | (sec[2] & 0xFF); int transportStreamId = ((sec[3] & 0xFF) << 8) | (sec[4] & 0xFF); int versionNumber = (sec[5] & 0x3E) >>> 1; int currentNextIndicator = sec[5] & 0x01; int sectionNumber = sec[6] & 0xFF; int lastSectionNumber = sec[7] & 0xFF; System.out.printf("[PAT] TS ID: %d, Ver: %d, Sec: %d/%d, Length: %d%n", transportStreamId, versionNumber, sectionNumber, lastSectionNumber, sectionLength); int pos = 8; // 跳过0..7字段 int end = sec.length - 4; // 减去CRC32 // 计算节目数量 int programCount = (end - pos) / 4; System.out.printf("[PAT] 节目数量: %d%n", programCount); while (pos + 4 <= end) { int programNumber = ((sec[pos] & 0xFF) << 8) | (sec[pos+1] & 0xFF); int pmtPid = ((sec[pos+2] & 0x1F) << 8) | (sec[pos+3] & 0xFF); pos += 4; if (programNumber == 0) { // NIT PID System.out.printf("[PAT] NIT -> PID %d%n", pmtPid); pidToProgram.put(pmtPid, 0); // NIT的节目号为0 continue; } Integer old = progToPmtPid.put(programNumber, pmtPid); if (old == null || !old.equals(pmtPid)) { System.out.printf("[PAT] 节目 %d -> PMT PID %d%n", programNumber, pmtPid); pidToProgram.put(pmtPid, programNumber); } } // 打印CRC32校验码 int crc32 = ((sec[end] & 0xFF) << 24) | ((sec[end+1] & 0xFF) << 16) | ((sec[end+2] & 0xFF) << 8) | (sec[end+3] & 0xFF); System.out.printf("[PAT] CRC32: 0x%08X%n", crc32); } static void parsePMT(byte[] sec) { int tableId = sec[0] & 0xFF; int sectionSyntaxIndicator = (sec[1] & 0x80) >>> 7; int sectionLength = ((sec[1] & 0x0F) << 8) | (sec[2] & 0xFF); int programNumber = ((sec[3] & 0xFF) << 8) | (sec[4] & 0xFF); int versionNumber = (sec[5] & 0x3E) >>> 1; int currentNextIndicator = sec[5] & 0x01; int sectionNumber = sec[6] & 0xFF; int lastSectionNumber = sec[7] & 0xFF; int pcrPid = ((sec[8] & 0x1F) << 8) | (sec[9] & 0xFF); int progInfoLen = ((sec[10] & 0x0F) << 8) | (sec[11] & 0xFF); System.out.printf("[PMT] 节目 %d, PCR PID: %d, 节目信息长度: %d%n", programNumber, pcrPid, progInfoLen); int pos = 12 + progInfoLen; int end = sec.length - 4; // 旧:仅收集 ES PID;新:同时收集详细信息 Set<Integer> es = new HashSet<Integer>(); List<EsInfo> list = new ArrayList<EsInfo>(); while (pos + 5 <= end) { int streamType = sec[pos] & 0xFF; int elementaryPid = ((sec[pos+1] & 0x1F) << 8) | (sec[pos+2] & 0xFF); int esInfoLen = ((sec[pos+3] & 0x0F) << 8) | (sec[pos+4] & 0xFF); // 取 ES 描述符(可能用于识别 AC-3/E-AC-3/DTS) byte[] esDesc = null; if (pos + 5 + esInfoLen <= end && esInfoLen > 0) { esDesc = new byte[esInfoLen]; System.arraycopy(sec, pos + 5, esDesc, 0, esInfoLen); } String[] cls = classifyStream(streamType, esDesc); // 见③ list.add(new EsInfo(elementaryPid, streamType, cls[0], cls[1])); es.add(elementaryPid); pidToProgram.put(elementaryPid, programNumber); System.out.printf("[PMT] ES PID %d, 类型: 0x%02X (%s - %s), 描述符长度: %d%n", elementaryPid, streamType, cls[0], cls[1], esInfoLen); pos += 5 + esInfoLen; } programEsPids.put(programNumber, es); // 兼容你之前的用法 programEsInfo.put(programNumber, list); // 新增:带类型的清单 System.out.printf("[PMT] 节目 %d ES PIDs %s%n", programNumber, es); } static String[] classifyStream(int streamType, byte[] esDesc) { // 返回 [kind, codec];kind: video/audio/other switch (streamType & 0xFF) { case 0x01: return new String[]{"video", "MPEG-1 Video"}; case 0x02: return new String[]{"video", "MPEG-2 Video"}; case 0x10: return new String[]{"video", "MPEG-4 Video"}; case 0x1B: return new String[]{"video", "H.264/AVC"}; case 0x24: return new String[]{"video", "HEVC/H.265"}; case 0x03: return new String[]{"audio", "MPEG-1 Layer II"}; case 0x04: return new String[]{"audio", "MPEG-2 Audio"}; case 0x0F: return new String[]{"audio", "AAC"}; case 0x11: return new String[]{"audio", "LATM/LOAS AAC"}; case 0x06: // 0x06(私有数据)常见通过描述符判定 AC-3 / E-AC-3 / DTS if (hasDescriptor(esDesc, (byte)0x6A)) return new String[]{"audio", "AC-3"}; if (hasDescriptor(esDesc, (byte)0x7A)) return new String[]{"audio", "E-AC-3"}; if (hasDescriptor(esDesc, (byte)0x7B)) return new String[]{"audio", "DTS"}; return new String[]{"other", "Private data"}; default: return new String[]{"other", String.format("stream_type 0x%02X", streamType & 0xFF)}; } } static boolean hasDescriptor(byte[] esDesc, byte tag) { if (esDesc == null) return false; int i = 0, n = esDesc.length; while (i + 2 <= n) { int t = esDesc[i] & 0xFF; int l = esDesc[i+1] & 0xFF; if (i + 2 + l > n) break; if ((byte)t == tag) return true; i += 2 + l; } return false; } static void parseSDT(byte[] sec) { int tableId = sec[0] & 0xFF; int sectionSyntaxIndicator = (sec[1] & 0x80) >>> 7; int sectionLength = ((sec[1] & 0x0F) << 8) | (sec[2] & 0xFF); int transportStreamId = ((sec[3] & 0xFF) << 8) | (sec[4] & 0xFF); int versionNumber = (sec[5] & 0x3E) >>> 1; int currentNextIndicator = sec[5] & 0x01; int sectionNumber = sec[6] & 0xFF; int lastSectionNumber = sec[7] & 0xFF; int originalNetworkId = ((sec[8] & 0xFF) << 8) | (sec[9] & 0xFF); int reservedFutureUse = sec[10] & 0xFF; System.out.printf("[SDT] TS ID: %d, ON ID: %d, Ver: %d, Sec: %d/%d%n", transportStreamId, originalNetworkId, versionNumber, sectionNumber, lastSectionNumber); int pos = 11; int end = sec.length - 4; while (pos + 5 <= end) { int serviceId = ((sec[pos] & 0xFF) << 8) | (sec[pos+1] & 0xFF); int reservedFutureUse2 = (sec[pos+2] & 0xFC) >>> 2; int eitScheduleFlag = (sec[pos+2] & 0x02) >>> 1; int eitPresentFollowingFlag = sec[pos+2] & 0x01; int runningStatus = (sec[pos+3] & 0xE0) >>> 5; int freeCaMode = (sec[pos+3] & 0x10) >>> 4; int descriptorsLoopLen = ((sec[pos+3] & 0x0F) << 8) | (sec[pos+4] & 0xFF); int descPos = pos + 5; int descEnd = descPos + descriptorsLoopLen; String name = null; System.out.printf("[SDT] 服务 ID: %d, 运行状态: %d, CA模式: %d, 描述符长度: %d%n", serviceId, runningStatus, freeCaMode, descriptorsLoopLen); while (descPos + 2 <= descEnd && descEnd <= end) { int tag = sec[descPos] & 0xFF; int len = sec[descPos+1] & 0xFF; if (descPos + 2 + len > descEnd) break; if (tag == 0x48 && len >= 3) { // service_descriptor int serviceType = sec[descPos+2] & 0xFF; int serviceProviderNameLen = sec[descPos+3] & 0xFF; int nameLenPos = descPos + 4 + serviceProviderNameLen; if (nameLenPos + 1 <= descPos + 2 + len) { int serviceNameLen = sec[nameLenPos] & 0xFF; int nameStart = nameLenPos + 1; int nameEnd = Math.min(nameStart + serviceNameLen, descPos + 2 + len); // JDK6没有Arrays.copyOfRange byte[] nameBytes = new byte[nameEnd - nameStart]; System.arraycopy(sec, nameStart, nameBytes, 0, nameEnd - nameStart); name = decodeDvbString(nameBytes); } System.out.printf("[SDT] 服务类型: 0x%02X, 名称: %s%n", serviceType, name); } descPos += 2 + len; } if (name != null && name.length() > 0) { programNames.put(serviceId, name); System.out.printf("[SDT] 节目 %d 名称='%s'%n", serviceId, name); } pos = descEnd; } // 打印CRC32校验码 int crc32 = ((sec[end] & 0xFF) << 24) | ((sec[end+1] & 0xFF) << 16) | ((sec[end+2] & 0xFF) << 8) | (sec[end+3] & 0xFF); System.out.printf("[SDT] CRC32: 0x%08X%n", crc32); } static String decodeDvbString(byte[] bs) { if (bs == null || bs.length == 0) return ""; int offset = 0; String charset = "GB18030"; // 国内台普遍用 int first = bs[0] & 0xFF; if (first == 0x10 && bs.length >= 3) { charset = "UTF-16BE"; offset = 1; } else if (first == 0x15 || first == 0x14) { charset = "GB2312"; offset = 1; } else if (first == 0x1F) { charset = "UTF-8"; offset = 1; } else if (first < 0x20) { // 还有其它DVB编码,通常国内不用 offset = 1; } else { // 无编码标志,直接用GB18030尝试 offset = 0; } try { return new String(bs, offset, bs.length - offset, charset).trim(); } catch (Exception e) { try { return new String(bs, offset, bs.length - offset, "GB2312").trim(); } catch (Exception ignore) {} try { return new String(bs, offset, bs.length - offset, "UTF-8").trim(); } catch (Exception ignore) {} return ""; } } static void maybeReport() { long now = System.nanoTime(); if (now - lastReportNs < REPORT_INTERVAL_NS) return; long dtNs = now - lastReportNs; lastReportNs = now; Map<Integer, Long> programBytes = new HashMap<Integer, Long>(); for (Map.Entry<Integer, Long> e : pidBytesCounter.entrySet()) { int pid = e.getKey().intValue(); long bytes = e.getValue().longValue(); Integer prog = pidToProgram.get(pid); if (prog != null) { Long old = programBytes.get(prog); programBytes.put(prog, (old == null ? 0L : old) + bytes); } } pidBytesCounter.clear(); if (programBytes.isEmpty()) return; System.out.println("----- 3s 统计 -----"); for (Map.Entry<Integer, Long> e : programBytes.entrySet()) { int program = e.getKey().intValue(); long bytes = e.getValue().longValue(); double mbps = (bytes * 8.0) / (dtNs / 1e9) / 1_000_000.0; String name = programNames.get(program); if (name == null) name = "(解析中…)"; // PMT PID 来自 PAT Integer pmtPid = progToPmtPid.get(program); // 选第一个视频、前两个音频 EsInfo v = null, a1 = null, a2 = null; List<EsInfo> list = programEsInfo.get(program); if (list != null) { for (int i = 0; i < list.size(); i++) { EsInfo es = list.get(i); if ("video".equals(es.kind) && v == null) { v = es; } else if ("audio".equals(es.kind)) { if (a1 == null) a1 = es; else if (a2 == null) a2 = es; } } } System.out.printf( "Program %d %-16s Rate: %.3f Mbit/s PMT:%s V:%s(%s) A1:%s(%s) A2:%s(%s)%n", program, name, mbps, (pmtPid == null ? "-" : String.valueOf(pmtPid)), (v==null ? "-" : String.valueOf(v.pid)), (v==null ? "-" : v.codec), (a1==null? "-" : String.valueOf(a1.pid)), (a1==null? "-" : a1.codec), (a2==null? "-" : String.valueOf(a2.pid)), (a2==null? "-" : a2.codec) ); } } // ===== PSI Section 重组器 ===== static class SectionAssembler { private final ByteArrayOutputStream cur = new ByteArrayOutputStream(); private Integer expectedLen = null; private final Queue<byte[]> ready = new LinkedList<byte[]>(); void push(byte[] src, int off, int len, boolean payloadStart, int continuityCounter) { int i = off; if (payloadStart) { int pointer = src[i] & 0xFF; i += 1; while (pointer > 0 && i < off + len) { i++; pointer--; } startNew(); } while (i < off + len) { if (expectedLen == null) { if (off + len - i < 3) { // 不够section头 write(src, i, off + len - i); return; } int sl = ((src[i+1] & 0x0F) << 8) | (src[i+2] & 0xFF); expectedLen = sl + 3; } int remaining = expectedLen.intValue() - cur.size(); int copy = Math.min(remaining, off + len - i); write(src, i, copy); i += copy; if (cur.size() == expectedLen.intValue()) { ready.add(cur.toByteArray()); startNew(); } } } boolean hasSection() { return !ready.isEmpty(); } byte[] pollSection() { return ready.poll(); } private void startNew() { cur.reset(); expectedLen = null; } private void write(byte[] src, int off, int len) { cur.write(src, off, len); } } } 帮我修改代码 解析 打印PAT表主要内容
09-19
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@page import="weaver.general.Util"%> <%@page import="weaver.conn.RecordSet"%> <%@page import="com.alibaba.fastjson.JSONObject"%> <%@page import="com.alibaba.fastjson.JSONArray"%> <%@page import="java.net.URLEncoder"%> <% request.setCharacterEncoding("UTF-8"); // 基础参数 String pddhRaw = Util.null2String(request.getParameter("PDDH")); String pddh = "0"; try { pddh = String.valueOf(Integer.parseInt(pddhRaw)); } catch(Exception e){ pddh = "0"; } // 查询参数(做简单清洗,避免注入/通配符滥用) String q_zcbm = Util.null2String(request.getParameter("q_zcbm")).replaceAll("[%'_]", ""); String q_syr = Util.null2String(request.getParameter("q_syr")).replaceAll("[%'_]", ""); String q_sybm = Util.null2String(request.getParameter("q_sybm")).replaceAll("[%'_]", ""); // 组装 SQL StringBuilder sql = new StringBuilder(); sql.append("select zcmc,zcbm,zcqc,zcgz,zclz,zcfl,ppxh,syr,sybm,rkrq,pdbz,zczt,pdsj,zcgs ") .append("from uf_CKBGQD where pddh=").append(pddh); if(q_zcbm.length()>0){ sql.append(" and zcbm like '%").append(q_zcbm).append("%'"); } if(q_syr.length()>0 ){ sql.append(" and syr like '%").append(q_syr ).append("%'"); } if(q_sybm.length()>0){ sql.append(" and sybm like '%").append(q_sybm).append("%'"); } // 查询 JSONArray jsonArray = new JSONArray(); RecordSet rs = new RecordSet(); rs.execute(sql.toString()); while(rs.next()){ JSONObject row = new JSONObject(); row.put("zcmc", rs.getString("zcmc")); row.put("zcbm", rs.getString("zcbm")); row.put("zcqc", rs.getString("zcqc")); row.put("zcgz", rs.getString("zcgz")); row.put("zclz", rs.getString("zclz")); row.put("zcfl", rs.getString("zcfl")); row.put("ppxh", rs.getString("ppxh")); row.put("syr", rs.getString("syr")); row.put("sybm", rs.getString("sybm")); // 使用部门 row.put("rkrq", rs.getString("rkrq")); row.put("pdbz", rs.getString("pdbz")); row.put("zczt", rs.getString("zczt")); row.put("pdsj", rs.getString("pdsj")); row.put("zcgs", rs.getString("zcgs")); // 资产归属 jsonArray.add(row); } // 把数据输出给前端 JS 使用(便于导出/前端处理) String dataJson = jsonArray.toJSONString(); %> <!DOCTYPE html> <html> <head> <title>查看报告</title> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"> <link rel="stylesheet" href="/cloudstore/resource/pc/com/v1/index.min.css?v=1715806801819"> <link rel="stylesheet" href="/cloudstore/resource/pc/com/v1/ecCom.min.css?v=1715806801819"> <script type="text/javascript" src="/js/My97DatePicker/WdatePicker.js" charset="gb2312"></script> <script type="text/javascript" src="/js/jquery/jquery-3.7.1.min.js"></script> <style> .toolbar { display:flex; gap:8px; align-items:center; padding:10px 0; flex-wrap:wrap; } .toolbar input { height:32px; padding:0 8px; } .toolbar .btn { height:32px; padding:0 12px; border:1px solid #d9d9d9; border-radius:4px; background:#fff; cursor:pointer; } .toolbar .btn.primary { background:#1677ff; color:#fff; border-color:#1677ff; } .action-link { color:#1677ff; cursor:pointer; } </style> </head> <body style="width:100%; height:100%;"> <div id="container"> <div class="coms-mode-docker coms-mode-search"> <div id="cube_search_9"> <div class="ant-spin-nested-loading"> <div class="ant-spin-container"> <div style="height: 100%;"> <div class="wea-new-top-content" style="height: 691.175px; overflow-y: hidden;"> <div class="cube-list-wrapper"> <!-- 查询工具条 & 导出 --> <form id="queryForm" method="get" class="toolbar"> <input type="hidden" name="PDDH" value="<%=pddh%>" /> <label>物料编码:</label> <input type="text" name="q_zcbm" value="<%=q_zcbm%>" placeholder="支持模糊查询"> <label>使用人:</label> <input type="text" name="q_syr" value="<%=q_syr%>" placeholder="支持模糊查询"> <label>使用部门:</label> <input type="text" name="q_sybm" value="<%=q_sybm%>" placeholder="支持模糊查询"> <button type="submit" class="btn primary">查询</button> <button type="button" class="btn" id="btnReset">重置</button> <button type="button" class="btn" id="btnExport">导出当前结果</button> </form> <div class="wea-new-table cube-list-table pageAutoWrap"> <div style="width: 100%; height: 100%;"> <div class="cube-list-table clearfix"> <div class="ant-spin-nested-loading"> <div class="ant-spin-container"> <div class="ant-table ant-table-large ant-table-fixed-header ant-table-scroll-position-left"> <div class="ant-table-content" style="padding-left: 0px; padding-right: 0px;"> <div class="ant-table-scroll"> <span> <div class="ant-table-header" style="overflow-x: scroll; margin-bottom: 0px !important; padding-bottom: 0px !important;"> <table class="ant-table-fixed" style="width: 100%;"> <colgroup> <col style="width: 14%"> <col style="width: 10%"> <col style="width: 14%"> <col style="width: 8%"> <col style="width: 8%"> <col style="width: 8%"> <col style="width: 10%"> <col style="width: 8%"> <col style="width: 10%"> <col style="width: 8%"> <col style="width: 8%"> <col style="width: 10%"> </colgroup> <thead class="ant-table-thead"> <tr style="height: 41.6px;"> <th class="react-resizable"><span class="ant-table-column-sorterN text-elli">物料编码</span></th> <th class="react-resizable"><span class="ant-table-column-sorterN text-elli">资产名称</span></th> <th class="react-resizable"><span class="ant-table-column-sorterN text-elli">资产全称</span></th> <th class="react-resizable"><span class="ant-table-column-sorterN text-elli">资产类属</span></th> <th class="react-resizable"><span class="ant-table-column-sorterN text-elli">资产归属</span></th> <th class="react-resizable"><span class="ant-table-column-sorterN text-elli">资产分类</span></th> <th class="react-resizable"><span class="ant-table-column-sorterN text-elli">品牌/型号</span></th> <th class="react-resizable"><span class="ant-table-column-sorterN text-elli">使用人</span></th> <th class="react-resizable"><span class="ant-table-column-sorterN text-elli">使用部门</span></th> <th class="react-resizable"><span class="ant-table-column-sorterN text-elli">入库日期</span></th> <th class="react-resizable"><span class="ant-table-column-sorterN text-elli">资产状态</span></th> <th class="react-resizable"><span class="ant-table-column-sorterN text-elli">操作</span></th> </tr> </thead> </table> </div> <div class="ant-table-body" style="overflow: auto scroll; max-height: 600px; min-height: auto;"> <table class="ant-table-fixed" style="width: 100%;" id="dataTable"> <colgroup> <col style="width: 14%"> <col style="width: 10%"> <col style="width: 14%"> <col style="width: 8%"> <col style="width: 8%"> <col style="width: 8%"> <col style="width: 10%"> <col style="width: 8%"> <col style="width: 10%"> <col style="width: 8%"> <col style="width: 8%"> <col style="width: 10%"> </colgroup> <tbody class="ant-table-tbody"> <% if(jsonArray.size()>0){ for(int i=0;i<jsonArray.size();i++){ %> <tr class="ant-table-row ant-table-row-level-0"> <td class="react-resizable"><span class="wea-url"><%=jsonArray.getJSONObject(i).getString("zcbm")%></span></td> <td class="react-resizable"><span class="wea-url"><%=jsonArray.getJSONObject(i).getString("zcmc")%></span></td> <td class="react-resizable"><span class="wea-url"><%=jsonArray.getJSONObject(i).getString("zcqc")%></span></td> <td class="react-resizable"><span class="wea-url"><%=jsonArray.getJSONObject(i).getString("zclz")%></span></td> <td class="react-resizable"><span class="wea-url"><%=jsonArray.getJSONObject(i).getString("zcgs")%></span></td> <td class="react-resizable"><span class="wea-url"><%=jsonArray.getJSONObject(i).getString("zcfl")%></span></td> <td class="react-resizable"><span class="wea-url"><%=jsonArray.getJSONObject(i).getString("ppxh")%></span></td> <td class="react-resizable"><span class="wea-url"><%=jsonArray.getJSONObject(i).getString("syr")%></span></td> <td class="react-resizable"><span class="wea-url"><%=jsonArray.getJSONObject(i).getString("sybm")%></span></td> <td class="react-resizable"><span class="wea-url"><%=jsonArray.getJSONObject(i).getString("rkrq")%></span></td> <td class="react-resizable"><span class="wea-url"><%=jsonArray.getJSONObject(i).getString("zczt")%></span></td> <td class="react-resizable"> <span class="action-link" onclick="onDelete(this)">删除</span> </td> </tr> <% } } %> </tbody> </table> </div> </span> </div> </div> </div> </div> </div> <!-- ant-spin-container --> </div> </div> </div> <!-- table wrap --> </div> </div> </div> </div> </div> <!-- spin --> </div> </div> </div> <script> // 前端可用数据(用于导出) const tableData = <%=dataJson%>; // 重置查询 $("#btnReset").on("click", function(){ const base = location.pathname + "?PDDH=<%=pddh%>"; location.href = base; }); // 一键导出(把当前结果导成 CSV) $("#btnExport").on("click", function(){ if(!tableData || tableData.length === 0){ alert("没有可导出的数据"); return; } const headers = ["物料编码","资产名称","资产全称","资产类属","资产归属","资产分类","品牌/型号","使用人","使用部门","入库日期","资产状态","盘点备注","盘点时间"]; const keys = ["zcbm","zcmc","zcqc","zclz","zcgs","zcfl","ppxh","syr","sybm","rkrq","zczt","pdbz","pdsj"]; // CSV 内容,含 BOM 以防中文乱码(Excel 友好) let csv = "\uFEFF" + headers.join(",") + "\n"; tableData.forEach(r=>{ const row = keys.map(k=>{ let val = (r[k] ?? "").toString().replace(/"/g,'""'); // 若包含逗号/引号/换行,按 CSV 规范用引号包裹 if(/[",\n]/.test(val)){ val = `"${val}"`; } return val; }).join(","); csv += row + "\n"; }); const blob = new Blob([csv], {type: "text/csv;charset=utf-8;"}); const url = URL.createObjectURL(blob); const a = document.createElement("a"); const ts = new Date(); const pad = n=> String(n).padStart(2,"0"); const name = `盘点清单_${ts.getFullYear()}${pad(ts.getMonth()+1)}${pad(ts.getDate())}_${pad(ts.getHours())}${pad(ts.getMinutes())}${pad(ts.getSeconds())}.csv`; a.href = url; a.download = name; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); }); // 删除:把该行的“物料编码”传给后端 function onDelete(el){ const $tr = $(el).closest("tr"); const zcbm = $tr.find("td").eq(0).text().trim(); // 第1列就是物料编码 if(!zcbm){ alert("未找到物料编码"); return; } if(!confirm("确认删除物料编码为【"+zcbm+"】的记录吗?")) return; // // TODO: 把 URL 换成你后端实际的删除接口 // $.ajax({ // url: "/api/ckbgqd/delete", // 例如:新建一个 Servlet/JSP 接口去处理删除 // type: "POST", // data: { zcbm: zcbm, pddh: "<%=pddh%>" }, // success: function(res){ // // 这里按你的后端返回格式调整 // // 假设返回 {success:true,msg:"ok"} // try{ // const r = typeof res === "string" ? JSON.parse(res) : res; // if(r.success){ // $tr.remove(); // }else{ // alert(r.msg || "删除失败"); // } // }catch(e){ // // 如果不是 JSON,就当成功处理 // $tr.remove(); // } // }, // error: function(){ // alert("请求失败,请稍后重试"); // } // }); var pddh = "<%=pddh%>"; <% String sql = "delete from uf_CKBGQD where pddh ='"<%=pddh%>"' and zcbm ="+"'"+zcbm+"'"; RecordSet rs1 = new RecordSet(); rs1.execute(rs1); %> } </script> </body> </html> 这个有错误,帮修复一下
10-24
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值